diff options
Diffstat (limited to 'system')
65 files changed, 0 insertions, 15613 deletions
diff --git a/system/CONTENTS b/system/CONTENTS deleted file mode 100644 index 62e5762..0000000 --- a/system/CONTENTS +++ /dev/null @@ -1,7 +0,0 @@ -X11 x window specific code -image image processing code -kernel the core pdp system (pool, queue, type, ...) -mmx mmx assembly code -pdbase base classes for pd objects -type different packet type implementations - diff --git a/system/Makefile b/system/Makefile deleted file mode 100644 index f3777f5..0000000 --- a/system/Makefile +++ /dev/null @@ -1,31 +0,0 @@ - -include ../Makefile.config - -all: $(PDP_TARGET) - -common: - make -C X11 - make -C png - make -C pdbase - make -C type - make -C kernel - make -C image $(PDP_TARGET) - -linux_mmx: common - make -C mmx - -linux: common - -darwin: common - -clean: - rm -f *~ - rm -f *.o - make -C mmx clean - make -C X11 clean - make -C png clean - make -C image clean - make -C pdbase clean - make -C type clean - make -C kernel clean - diff --git a/system/X11/Makefile b/system/X11/Makefile deleted file mode 100644 index 0001c49..0000000 --- a/system/X11/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -OBJECTS = pdp_xwindow.o - - -include ../../Makefile.config - -all: $(OBJECTS) - -clean: - rm -f *~ - rm -f *.o diff --git a/system/X11/pdp_xvideo.c b/system/X11/pdp_xvideo.c deleted file mode 100644 index dab060d..0000000 --- a/system/X11/pdp_xvideo.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Pure Data Packet system module. - x window glue code (fairly tied to pd and pdp) - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -// this code is fairly tied to pd and pdp. serves mainly as reusable glue code -// for pdp_xv, pdp_glx, pdp_3d_windowcontext, ... - -#include <string.h> - -#include "pdp_xwindow.h" -#include "pdp_xvideo.h" -#include "pdp_post.h" -#include "pdp_packet.h" - -#define D if(0) - - - - -/************************************* PDP_XVIDEO ************************************/ - -static void pdp_xvideo_create_xvimage(t_pdp_xvideo *xvid, int width, int height) -{ - int i; - long size; - - //post("pdp_xvideo_create_xvimage"); - - xvid->width = width; - xvid->height = height; - size = (xvid->width * xvid->height + (((xvid->width>>1)*(xvid->height>>1))<<1)); - //post("create xvimage %d %d", xvid->width, xvid->height); - xvid->data = (unsigned char *)pdp_alloc(size); - for (i=0; i<size; i++) xvid->data[i] = i; - xvid->xvi = XvCreateImage(xvid->xdpy->dpy, xvid->xv_port, xvid->xv_format, (char *)xvid->data, xvid->width, xvid->height); - xvid->last_encoding = -1; - if ((!xvid->xvi) || (!xvid->data)) pdp_post ("ERROR CREATING XVIMAGE"); - //pdp_post("created xvimag data:%x xvi:%x",xvid->data,xvid->xvi); - -} - -static void pdp_xvideo_destroy_xvimage(t_pdp_xvideo *xvid) -{ - if(xvid->data) pdp_dealloc(xvid->data); - if (xvid->xvi) XFree(xvid->xvi); - xvid->xvi = 0; - xvid->data = 0; -} - -void pdp_xvideo_display_packet(t_pdp_xvideo *xvid, t_pdp_xwindow *xwin, int packet) -{ - t_pdp *header = pdp_packet_header(packet); - void *data = pdp_packet_data(packet); - t_bitmap * bm = pdp_packet_bitmap_info(packet); - unsigned int width, height, encoding, size, nbpixels; - - /* some checks: only display when initialized and when pacet is bitmap YV12 */ - if (!xvid->initialized) return; - if (!header) return; - if (!bm) return; - - width = bm->width; - height = bm->height; - encoding = bm->encoding; - size = (width * height + (((width>>1)*(height>>1))<<1)); - nbpixels = width * height; - - if (PDP_BITMAP != header->type) return; - if (PDP_BITMAP_YV12 != encoding) return; - - /* check if xvimage needs to be recreated */ - if ((width != xvid->width) || (height != xvid->height)){ - //pdp_post("pdp_xv: replace image"); - pdp_xvideo_destroy_xvimage(xvid); - pdp_xvideo_create_xvimage(xvid, width, height); - } - - /* copy the data to the XvImage buffer */ - memcpy(xvid->data, data, size); - - /* display */ - XvPutImage(xvid->xdpy->dpy,xvid->xv_port, xwin->win,xwin->gc,xvid->xvi, - 0,0,xvid->width,xvid->height, 0,0,xwin->winwidth,xwin->winheight); - XFlush(xvid->xdpy->dpy); - - - -} - - - -void pdp_xvideo_close(t_pdp_xvideo* xvid) -{ - if (xvid->initialized){ - if (xvid->xvi) pdp_xvideo_destroy_xvimage(xvid); - XvUngrabPort(xvid->xdpy->dpy, xvid->xv_port, CurrentTime); - xvid->xv_port = 0; - xvid->xdpy = 0; - xvid->last_encoding = -1; - xvid->initialized = false; - } -} - -void pdp_xvideo_cleanup(t_pdp_xvideo* xvid) -{ - // close xvideo port (and delete XvImage) - pdp_xvideo_close(xvid); - - // no more dynamic data to free - -} - -void pdp_xvideo_free(t_pdp_xvideo* xvid){ - pdp_xvideo_cleanup(xvid); - pdp_dealloc(xvid); -} - -void pdp_xvideo_init(t_pdp_xvideo *xvid) -{ - - xvid->xdpy = 0; - - xvid->xv_format = FOURCC_YV12; - xvid->xv_port = 0; - - xvid->width = 320; - xvid->height = 240; - - xvid->data = 0; - xvid->xvi = 0; - - xvid->initialized = 0; - xvid->last_encoding = -1; - -} -t_pdp_xvideo *pdp_xvideo_new(void) -{ - t_pdp_xvideo *xvid = pdp_alloc(sizeof(*xvid)); - pdp_xvideo_init(xvid); - return xvid; -} - -int pdp_xvideo_open_on_display(t_pdp_xvideo *xvid, t_pdp_xdisplay *d) -{ - unsigned int ver, rel, req, ev, err, i, j; - unsigned int adaptors; - int formats; - XvAdaptorInfo *ai; - - if (xvid->initialized) return 1; - if (!d) return 0; - xvid->xdpy = d; - - if (Success != XvQueryExtension(xvid->xdpy->dpy,&ver,&rel,&req,&ev,&err)) return 0; - - /* find + lock port */ - if (Success != XvQueryAdaptors(xvid->xdpy->dpy,DefaultRootWindow(xvid->xdpy->dpy),&adaptors,&ai)) - return 0; - for (i = 0; i < adaptors; i++) { - if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask)) { - for (j=0; j < ai[i].num_ports; j++){ - if (Success != XvGrabPort(xvid->xdpy->dpy,ai[i].base_id+j,CurrentTime)) { - //fprintf(stderr,"INFO: Xvideo port %ld on adapter %d: is busy, skipping\n",ai[i].base_id+j, i); - } - else { - xvid->xv_port = ai[i].base_id + j; - goto breakout; - } - } - } - } - - - breakout: - - XFree(ai); - if (0 == xvid->xv_port) return 0; - pdp_post("pdp_xvideo: grabbed port %d on adaptor %d", xvid->xv_port, i); - xvid->initialized = 1; - pdp_xvideo_create_xvimage(xvid, xvid->width, xvid->height); - return 1; -} - - diff --git a/system/X11/pdp_xwindow.c b/system/X11/pdp_xwindow.c deleted file mode 100644 index 563ee21..0000000 --- a/system/X11/pdp_xwindow.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Pure Data Packet system module. - x window glue code (fairly tied to pd and pdp) - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -// this code is fairly tied to pd and pdp. serves mainly as reusable glue code -// for pdp_xv, pdp_glx, pdp_3d_windowcontext, ... - - -#include "pdp.h" -#include "pdp_xwindow.h" - -#define D if(0) - - -static void pdp_xwindow_overrideredirect(t_pdp_xwindow *xwin, int b) -{ - XSetWindowAttributes new_attr; - new_attr.override_redirect = b ? True : False; - XChangeWindowAttributes(xwin->dpy, xwin->win, CWOverrideRedirect, &new_attr); - //XFlush(xwin->dpy); - -} - - -void pdp_xwindow_moveresize(t_pdp_xwindow *xwin, int xoffset, int yoffset, int width, int height) -{ - - D post("_pdp_xwindow_moveresize"); - if ((width > 0) && (height > 0)){ - xwin->winwidth = width; - xwin->winheight = height; - xwin->winxoffset = xoffset; - xwin->winyoffset = yoffset; - - if (xwin->initialized){ - XMoveResizeWindow(xwin->dpy, xwin->win, xoffset, yoffset, width, height); - XFlush(xwin->dpy); - } - } -} - - -void pdp_xwindow_fullscreen(t_pdp_xwindow *xwin) -{ - XWindowAttributes rootwin_attr; - - D post("pdp_xwindow_fullscreen"); - - /* hmm.. fullscreen and xlib the big puzzle.. - if it looks like a hack it is a hack. */ - - if (xwin->initialized){ - - XGetWindowAttributes(xwin->dpy, RootWindow(xwin->dpy, xwin->screen), &rootwin_attr ); - - //pdp_xwindow_overrideredirect(xwin, 0); - pdp_xwindow_moveresize(xwin, 0, 0, rootwin_attr.width, rootwin_attr.height); - //pdp_xwindow_overrideredirect(xwin, 1); - //XRaiseWindow(xwin->dpy, xwin->win); - //pdp_xwindow_moveresize(xwin, 0, 0, rootwin_attr.width, rootwin_attr.height); - //pdp_xwindow_overrideredirect(xwin, 0); - - - - - } -} - - -void pdp_xwindow_tile(t_pdp_xwindow *xwin, int x_tiles, int y_tiles, int i, int j) -{ - XWindowAttributes rootwin_attr; - XSetWindowAttributes new_attr; - - D post("pdp_xwindow_fullscreen"); - - if (xwin->initialized){ - int tile_w; - int tile_h; - XGetWindowAttributes(xwin->dpy, RootWindow(xwin->dpy, xwin->screen), &rootwin_attr ); - - tile_w = rootwin_attr.width / x_tiles; - tile_h = rootwin_attr.height / y_tiles; - - xwin->winwidth = (x_tiles-1) ? rootwin_attr.width - (x_tiles-1)*tile_w : tile_w; - xwin->winheight = (y_tiles-1) ? rootwin_attr.height - (y_tiles-1)*tile_h : tile_h; - xwin->winxoffset = i * tile_w; - xwin->winyoffset = j * tile_h; - - //new_attr.override_redirect = True; - //XChangeWindowAttributes(xwin->dpy, xwin->win, CWOverrideRedirect, &new_attr ); - XMoveResizeWindow(xwin->dpy, xwin->win, xwin->winxoffset, xwin->winyoffset, xwin->winwidth, xwin->winheight); - - } -} - -/* resize window */ -void pdp_xwindow_resize(t_pdp_xwindow *xwin, int width, int height) -{ - D post("pdp_xwindow_resize"); - if ((width > 0) && (height > 0)){ - xwin->winwidth = width; - xwin->winheight = height; - if (xwin->initialized){ - XResizeWindow(xwin->dpy, xwin->win, width, height); - XFlush(xwin->dpy); - } - } - //_pdp_xwindow_moveresize(xwin, xwin->winxoffset, xwin->winyoffset, width, height); -} - -/* move window */ -void pdp_xwindow_move(t_pdp_xwindow *xwin, int xoffset, int yoffset) -{ - D post("pdp_xwindow_move"); - pdp_xwindow_moveresize(xwin, xoffset, yoffset, xwin->winwidth, xwin->winheight); -} - -/* send events to a pd outlet (don't call this outside the pd thread) */ -void pdp_xwindow_send_events(t_pdp_xwindow *xwin, t_outlet *outlet) -{ - - unsigned int i; - XEvent e; - XConfigureEvent *ce = (XConfigureEvent *)&e; - XButtonEvent *be = (XButtonEvent *)&e; - XMotionEvent *me = (XMotionEvent *)&e; - t_symbol *s; - t_atom atom[2]; - char nextdrag[]="drag0"; - char but='0'; - float inv_x = 1.0f / (float)(xwin->winwidth); - float inv_y = 1.0f / (float)(xwin->winheight); - int nbEvents = XEventsQueued(xwin->dpy, QueuedAlready); - - - -#if 0 - while (nbEvents && XPending(xwin->dpy)){ - XNextEvent(xwin->dpy, &e); - nbEvents--; - if (e.xany.window != xwin->win) { - XPutBackEvent(xwin->dpy, &e); - continue; - } -#else - - while (XPending(xwin->dpy)){ - XNextEvent(xwin->dpy, &e); - //if (e.xany.window != xwin->win) continue; -#endif - - switch(e.type){ - case ConfigureNotify: - xwin->winwidth = ce->width; - xwin->winheight = ce->height; - inv_x = 1.0f / (float)(xwin->winwidth); - inv_y = 1.0f / (float)(xwin->winheight); - break; - - case ClientMessage: - if ((Atom)e.xclient.data.l[0] == xwin->WM_DELETE_WINDOW) { - //post("pdp_xv: button disabled, please send a \"close\" message to close the window"); - //pdp_xv_kaboom(x); - //destroy = 1; - } - break; - - case ButtonPress: - //post("pdp_xv: press %f %f", inv_x * (float)be->x, inv_y * (float)be->y); - SETFLOAT(atom+0,inv_x * (float)be->x); - SETFLOAT(atom+1,inv_y * (float)be->y); - outlet_anything(outlet, gensym("press"), 2, atom); - switch(be->button){ - case Button1: outlet_anything(outlet, gensym("press1"), 2, atom); but='1'; break; - case Button2: outlet_anything(outlet, gensym("press2"), 2, atom); but='2'; break; - case Button3: outlet_anything(outlet, gensym("press3"), 2, atom); but='3'; break; - case Button4: outlet_anything(outlet, gensym("press4"), 2, atom); but='4'; break; - case Button5: outlet_anything(outlet, gensym("press5"), 2, atom); but='5'; break; - default: break; - } - nextdrag[4]=but; - xwin->dragbutton = gensym(nextdrag); - break; - - case ButtonRelease: - //post("pdp_xv: release %f %f", inv_x * (float)be->x, inv_y * (float)be->y); - SETFLOAT(atom+0,inv_x * (float)be->x); - SETFLOAT(atom+1,inv_y * (float)be->y); - outlet_anything(outlet, gensym("release"), 2, atom); - switch(be->button){ - case Button1: outlet_anything(outlet, gensym("release1"), 2, atom); break; - case Button2: outlet_anything(outlet, gensym("release2"), 2, atom); break; - case Button3: outlet_anything(outlet, gensym("release3"), 2, atom); break; - case Button4: outlet_anything(outlet, gensym("release4"), 2, atom); break; - case Button5: outlet_anything(outlet, gensym("release5"), 2, atom); break; - default: break; - } - - break; - case MotionNotify: - //post("pdp_xv: drag %f %f", inv_x * (float)be->x, inv_y * (float)be->y); - SETFLOAT(atom+0,inv_x * (float)be->x); - SETFLOAT(atom+1,inv_y * (float)be->y); - outlet_anything(outlet, gensym("drag"), 2, atom); - outlet_anything(outlet, xwin->dragbutton, 2, atom); - break; - - default: - //post("pdp_xv: unknown event"); - break; - } - - } - -} - - - -void pdp_xwindow_cursor(t_pdp_xwindow *xwin, t_floatarg f) -{ - if (!xwin->initialized) return; - - if (f == 0) { - static char data[] = {0}; - - Cursor cursor; - Pixmap blank; - XColor dummy; - - blank = XCreateBitmapFromData(xwin->dpy, xwin->win, data, 1, 1); - cursor = XCreatePixmapCursor(xwin->dpy, blank, blank, &dummy, - &dummy, 0, 0); - XFreePixmap(xwin->dpy, blank); - XDefineCursor(xwin->dpy, xwin->win,cursor); - } - else - XUndefineCursor(xwin->dpy, xwin->win); - - xwin->cursor = f; -} - -/* create xwindow */ -int pdp_xwindow_create_on_display(t_pdp_xwindow *xwin, Display *dpy) -{ - XEvent e; - unsigned int i; - - /* check if already opened */ - if( xwin->initialized ){ - post("pdp_xwindow_create_on_display: window already created"); - goto exit; - } - - xwin->dpy = dpy; - - /* create a window */ - xwin->screen = DefaultScreen(xwin->dpy); - - - xwin->win = XCreateSimpleWindow( - xwin->dpy, - RootWindow(xwin->dpy, xwin->screen), xwin->winxoffset, xwin->winyoffset, xwin->winwidth, xwin->winheight, 0, - BlackPixel(xwin->dpy, xwin->screen), - BlackPixel(xwin->dpy, xwin->screen)); - - - /* enable handling of close window event */ - xwin->WM_DELETE_WINDOW = XInternAtom(xwin->dpy, "WM_DELETE_WINDOW", True); - (void)XSetWMProtocols(xwin->dpy, xwin->win, &xwin->WM_DELETE_WINDOW, 1); - - if(!(xwin->win)){ - /* clean up mess */ - post("pdp_xwindow_create_on_display: could not create window. closing.\n"); - //XCloseDisplay(xwin->dpy); NOT OWNER - xwin->dpy = 0; - xwin->initialized = false; - goto exit; - } - - /* select input events */ - XSelectInput(xwin->dpy, xwin->win, StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | MotionNotify | ButtonMotionMask); - //XSelectInput(xwin->dpy, xwin->win, StructureNotifyMask); - - - /* set window title */ - XStoreName(xwin->dpy, xwin->win, "pdp"); - - - /* map */ - XMapWindow(xwin->dpy, xwin->win); - - /* create graphics context */ - xwin->gc = XCreateGC(xwin->dpy, xwin->win, 0, 0); - - /* catch mapnotify */ - for(;;){ - XNextEvent(xwin->dpy, &e); - if (e.type == MapNotify) break; - } - - - /* we're done initializing */ - xwin->initialized = true; - - /* disable/enable cursor */ - pdp_xwindow_cursor(xwin, xwin->cursor); - - exit: - return xwin->initialized; - -} - -void pdp_xwindow_init(t_pdp_xwindow *xwin) -{ - xwin->dpy = 0; - xwin->screen = -1; - - xwin->winwidth = 320; - xwin->winheight = 240; - xwin->winxoffset = 0; - xwin->winyoffset = 0; - - xwin->initialized = 0; - - xwin->cursor = 0; - xwin->dragbutton = gensym("drag1"); - -} - - -void pdp_xwindow_close(t_pdp_xwindow *xwin) -{ - - XEvent e; - - if (xwin->initialized){ - XFreeGC(xwin->dpy, xwin->gc); - XDestroyWindow(xwin->dpy, xwin->win); - while(XPending(xwin->dpy)) XNextEvent(xwin->dpy, &e); - xwin->dpy = 0; - xwin->initialized = false; - } - -} - -void pdp_xwindow_free(t_pdp_xwindow *x) -{ - // close win - pdp_xwindow_close(x); - - // no more dynamic data to free -} - - - -// some more x specific stuff: XVideo - -static void pdp_xvideo_create_xvimage(t_pdp_xvideo *xvid, int width, int height) -{ - int i; - long size; - - //post("pdp_xvideo_create_xvimage"); - - xvid->width = width; - xvid->height = height; - size = (xvid->width * xvid->height + (((xvid->width>>1)*(xvid->height>>1))<<1)); - //post("create xvimage %d %d", xvid->width, xvid->height); - xvid->data = (unsigned char *)pdp_alloc(size); - for (i=0; i<size; i++) xvid->data[i] = i; - xvid->xvi = XvCreateImage(xvid->dpy, xvid->xv_port, xvid->xv_format, (char *)xvid->data, xvid->width, xvid->height); - xvid->last_encoding = -1; - if ((!xvid->xvi) || (!xvid->data)) post ("ERROR CREATING XVIMAGE"); - //post("created xvimag data:%x xvi:%x",xvid->data,xvid->xvi); - -} - -static void pdp_xvideo_destroy_xvimage(t_pdp_xvideo *xvid) -{ - if(xvid->data) pdp_dealloc(xvid->data); - if (xvid->xvi) XFree(xvid->xvi); - xvid->xvi = 0; - xvid->data = 0; -} - -void pdp_xvideo_display_packet(t_pdp_xvideo *xvid, t_pdp_xwindow *xwin, int packet) -{ - t_pdp *header = pdp_packet_header(packet); - void *data = pdp_packet_data(packet); - t_bitmap * bm = pdp_packet_bitmap_info(packet); - unsigned int width, height, encoding, size, nbpixels; - - /* some checks: only display when initialized and when pacet is bitmap YV12 */ - if (!xvid->initialized) return; - if (!header) return; - if (!bm) return; - - width = bm->width; - height = bm->height; - encoding = bm->encoding; - size = (width * height + (((width>>1)*(height>>1))<<1)); - nbpixels = width * height; - - if (PDP_BITMAP != header->type) return; - if (PDP_BITMAP_YV12 != encoding) return; - - /* check if xvimage needs to be recreated */ - if ((width != xvid->width) || (height != xvid->height)){ - //post("pdp_xv: replace image"); - pdp_xvideo_destroy_xvimage(xvid); - pdp_xvideo_create_xvimage(xvid, width, height); - } - - /* copy the data to the XvImage buffer */ - memcpy(xvid->data, data, size); - - /* display */ - XvPutImage(xvid->dpy,xvid->xv_port, xwin->win,xwin->gc,xvid->xvi, - 0,0,xvid->width,xvid->height, 0,0,xwin->winwidth,xwin->winheight); - XFlush(xvid->dpy); - - - -} - - - -void pdp_xvideo_close(t_pdp_xvideo* xvid) -{ - if (xvid->initialized){ - if (xvid->xvi) pdp_xvideo_destroy_xvimage(xvid); - XvUngrabPort(xvid->dpy, xvid->xv_port, CurrentTime); - xvid->xv_port = 0; - xvid->dpy = 0; - xvid->screen = -1; - xvid->last_encoding = -1; - xvid->initialized = false; - } -} - -void pdp_xvideo_free(t_pdp_xvideo* xvid) -{ - // close xvideo port (and delete XvImage) - pdp_xvideo_close(xvid); - - // no more dynamic data to free - -} - -void pdp_xvideo_init(t_pdp_xvideo *xvid) -{ - - xvid->dpy = 0; - xvid->screen = -1; - - xvid->xv_format = FOURCC_YV12; - xvid->xv_port = 0; - - xvid->width = 320; - xvid->height = 240; - - xvid->data = 0; - xvid->xvi = 0; - - xvid->initialized = 0; - xvid->last_encoding = -1; - -} - -int pdp_xvideo_open_on_display(t_pdp_xvideo *xvid, Display *dpy) -{ - unsigned int ver, rel, req, ev, err, i, j; - unsigned int adaptors; - int formats; - XvAdaptorInfo *ai; - - if (xvid->initialized) return 1; - if (!dpy) return 0; - xvid->dpy = dpy; - - if (Success != XvQueryExtension(xvid->dpy,&ver,&rel,&req,&ev,&err)) return 0; - - /* find + lock port */ - if (Success != XvQueryAdaptors(xvid->dpy,DefaultRootWindow(xvid->dpy),&adaptors,&ai)) - return 0; - for (i = 0; i < adaptors; i++) { - if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask)) { - for (j=0; j < ai[i].num_ports; j++){ - if (Success != XvGrabPort(xvid->dpy,ai[i].base_id+j,CurrentTime)) { - //fprintf(stderr,"INFO: Xvideo port %ld on adapter %d: is busy, skipping\n",ai[i].base_id+j, i); - } - else { - xvid->xv_port = ai[i].base_id + j; - goto breakout; - } - } - } - } - - - breakout: - - XFree(ai); - if (0 == xvid->xv_port) return 0; - post("pdp_xvideo: grabbed port %d on adaptor %d", xvid->xv_port, i); - xvid->initialized = 1; - pdp_xvideo_create_xvimage(xvid, xvid->width, xvid->height); - return 1; -} - - diff --git a/system/image/Makefile b/system/image/Makefile deleted file mode 100644 index f9ed52c..0000000 --- a/system/image/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../../Makefile.config - -all: $(PDP_TARGET) - -OBJECTS = pdp_llconv.o pdp_resample.o pdp_imageproc_common.o - -OBJECTS_MMX = pdp_imageproc_mmx.o pdp_llconv_mmx.o -OBJECTS_PORTABLE = pdp_imageproc_portable.o pdp_llconv_portable.o - - - - -linux_mmx: $(OBJECTS_MMX) $(OBJECTS) - -linux: $(OBJECTS_PORTABLE) $(OBJECTS) - -darwin: $(OBJECTS_PORTABLE) $(OBJECTS) - -clean: - rm -f *~ - rm -f *.o diff --git a/system/image/pdp_imageproc_common.c b/system/image/pdp_imageproc_common.c deleted file mode 100644 index bc34b79..0000000 --- a/system/image/pdp_imageproc_common.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Pure Data Packet. common image processing routines. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* - This file contains common code for (portable) low level image processing objects - pdp_imageproc_* methods - The rest is int pdp_imageproc_<platform>.c - - There are also highlevel dispatcher methods that operate on packets: - pdp_imageproc_dispatch_* methods - -*/ - -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include "pdp.h" - -#define CLAMP16(x) (((x) > 0x7fff) ? 0x7fff : (((x) < -0x7fff) ? -0x7fff : (x))) - -u32 pdp_imageproc_legalwidth(int i) -{ - if (i>1024) return 1024; - if (i>0) return ((((i-1)>>3)+1)<<3); - return 8; - -} - -u32 pdp_imageproc_legalheight(int i) -{ - if (i>1024) return 1024; - if (i>0) return ((((i-1)>>3)+1)<<3); - return 8; -} -u32 pdp_imageproc_legalwidth_round_down(int i) -{ - if (i>1024) return 1024; - if (i>8) return ((i>>3)<<3); - return 8; - -} - -u32 pdp_imageproc_legalheight_round_down(int i) -{ - if (i>1024) return 1024; - if (i>8) return ((i>>3)<<3); - return 8; -} - - - -/* some operations */ - -/* logic operators */ - -void pdp_imageproc_xor_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - u32 *plane = (u32 *)image; - u32 *plane2 = (u32 *)image2; - int count = (width * height) >> 1; - int i; - - for (i=0; i<count; i++){ - plane[i] ^= plane2[i]; - } -} - -void pdp_imageproc_and_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - u32 *plane = (u32 *)image; - u32 *plane2 = (u32 *)image2; - int count = (width * height) >> 1; - int i; - - for (i=0; i<count; i++){ - plane[i] &= plane2[i]; - } -} - -void pdp_imageproc_or_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - u32 *plane = (u32 *)image; - u32 *plane2 = (u32 *)image2; - int count = (width * height) >> 1; - int i; - - for (i=0; i<count; i++){ - plane[i] |= plane2[i]; - } -} - -void pdp_imageproc_not_process(void *x, u32 width, u32 height, s16 *image) -{ - u32 *plane = (u32 *)image; - int count = (width * height) >> 1; - int i; - - for (i=0; i<count; i++){ - plane[i] ^= 0xffffffff; - } -} - -void pdp_imageproc_mask_process(void *x, u32 width, u32 height, s16 *image) -{ - u32 mask = (u32)x; - u32 *plane = (u32 *)image; - int count = (width * height) >> 1; - int i; - - mask = (mask & 0xffff) | (mask << 16); - - for (i=0; i<count; i++){ - plane[i] &= mask; - } -} - -// produce a plasma image -// note: random number generator can be platform specific -// however, it should be seeded. (same seed produces the same result) - -typedef struct -{ - u32 seed; - s32 scale; -} t_plasma; - -static inline s16 _rand_s16(void) -{ - return (s16)(random()<<0); -} - -static inline s16 _new_color(s32 one, s32 two, s32 scale) -{ - return CLAMP16((one >> 1) + (two >> 1) + ((scale * _rand_s16()) >> 16)); - //return (one >> 1) + (two >> 1); -} - -void *pdp_imageproc_plasma_new(void){return pdp_alloc(sizeof(t_plasma));} -void pdp_imageproc_plasma_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_plasma_setseed(void *x, float seed) -{ - *((float *)x) = seed; -} -void pdp_imageproc_plasma_setturbulence(void *x, float f) -{ - ((t_plasma *)x)->scale = CLAMP16(f * ((float)0x7fff)); -} - -static void _plasma_subdiv(u32 w, u32 h, u32 s, s16 *image, int calc_left, int calc_top, s32 scale) -{ - int w0 = ((w-1)>>1); // width of left segments - int h0 = ((h-1)>>1); // heigth of top segments - int w1 = w - w0; - int h1 = h - h0; - - /* conditions: w0 <= w1, h0 <= h1 */ - - /* original coordinates */ - int topleft = 0; - int topright = w-1; - int bottomleft = s * (h-1); - int bottomright = bottomleft + topright; - - /* new subdivision coordinates */ - int top = w0; - int left = s * h0; - int bottom = bottomleft + w0; - int right = topright + left; - int center = left + top; - - if (w0 && h0){ /* left-right and top-bottom subdivide */ - - /* calculate corner pixel colours */ - if (calc_top) image[top] = _new_color(image[topleft], image[topright], scale); - if (calc_left) image[left] = _new_color(image[topleft], image[bottomleft], scale); - image[right] = _new_color(image[topright], image[bottomright], scale); - image[bottom] = _new_color(image[bottomleft], image[bottomright], scale); - image[center] = (_new_color(image[top], image[bottom], scale) >> 1) - +(_new_color(image[left], image[right], scale) >> 1); - - - /* subdivide (with overlap) */ - _plasma_subdiv(w0+1, h0+1, s, &image[topleft], 1, 1, scale); - _plasma_subdiv(w1, h0+1, s, &image[top], 0, 1, scale); - _plasma_subdiv(w0+1, h1, s, &image[left], 1, 0, scale); - _plasma_subdiv(w1, h1, s, &image[center], 0, 0, scale); - - } - - - else if(h0) { /* top-bottom subdivide */ - - //post("h:%d", h); - - /* calculate corner pixel colours */ - if(calc_left) image[left] = _new_color(image[topleft], image[bottomleft], scale); - image[right] = _new_color(image[topright], image[bottomright], scale); - - /* subdivide (without overlap) */ - _plasma_subdiv(w, h0+1, s, &image[topleft], 1, 0, scale); - _plasma_subdiv(w, h1, s, &image[left], 1, 0, scale); - - } - - else if (w0){ /* left-right subdivide */ - - /* calculate corner pixel colours */ - if (calc_top) image[top] = _new_color(image[topleft], image[topright], scale); - image[bottom] = _new_color(image[bottomleft], image[bottomright],scale); - - /* subdivide with overlap */ - _plasma_subdiv(w0+1, h, s, &image[topleft], 0, 1, scale); - _plasma_subdiv(w1, h, s, &image[top], 0, 1, scale); - - } - -} - -void pdp_imageproc_plasma_process(void *x, u32 width, u32 height, s16 *image) -{ - s32 scale = (((t_plasma *)x)->scale); - srandom (((t_plasma *)x)->seed); - - /* set initial border colours */ - image[0] = _rand_s16(); - image[width-1] = _rand_s16(); - image[width * (height-1)] = _rand_s16(); - image[width * height - 1] = _rand_s16(); - - /* subdivide */ - _plasma_subdiv(width, height, width, image, 1, 1, scale); - - ((t_plasma *)x)->seed = random(); - -} - - - -void pdp_imageproc_zero_process(void *x, u32 width, u32 height, s16 *image) -{ - int bytesize = (width * height) << 1; - memset(image, 0, bytesize); -} - -void pdp_imageproc_constant_process(void *x, u32 width, u32 height, s16 *image) -{ - int i; - u32 value = (u32)x; - u32 *plane = (u32 *)image; - int wordsize = (width * height) >> 1; - value = (value & 0xffff) | (value << 16); - for (i=0; i<wordsize; i++){ - plane[i] = value; - } -} - - -/* other stateless operators */ - -/* some 2x16bit vector ops */ - -/* some bit shuffling to ensure 32 bit accesses - get the sign bit extended as a mask: - : 0xffff +: 0x0000 */ -static inline u32 _sign(s32 invec) -{ - s32 mask_top = invec; - s32 mask_bot = invec; - - mask_top &= 0x80000000; /* isolate top sign bit */ - mask_bot <<= 16; /* shift bottom word to top word */ - mask_bot &= 0x80000000; /* isolate bottom sign bit */ - mask_top >>= 15; /* shift sign bit into top word */ - mask_bot >>= 15; - ((u32)mask_bot) >>=16; /* shift top word into bottom word */ - return mask_top |mask_bot; -} - -/* clear the least significant bit of the top word - to ensure a decoupled vector add */ -static inline void _decouple(s32 *invec) -{ - *invec &= 0xfffeffff; -} - -void pdp_imageproc_abs_process(void *x, u32 width, u32 height, s16 *image) -{ - int i; - s32 *wimage = (s32 *)image; - int wsize = (width * height) >> 1; - for (i=0; i<wsize; i++){ - /* this computes c = (c >= 0) ? (c) : (~c) */ - /* not is used instead of neg to prevent overflow on 0x8000 */ - /* this maps both 0 and -1 to 0 */ - - wimage[i] ^= _sign(wimage[i]); - - } -} - -void pdp_imageproc_zthresh_process(void *x, u32 width, u32 height, s16 *image) -{ - int i; - s32 *wimage = (s32 *)image; - int wsize = (width * height) >> 1; - for (i=0; i<wsize; i++){ - /* this computes c = (c >= 0) ? (c) : (0) */ - wimage[i] &= ~_sign(wimage[i]); - } -} - -/* hard thresholding: x contains a positive unsigned short int */ -void pdp_imageproc_hardthresh_process(void *x, u32 width, u32 height, s16 *image) -{ - int i; - s32 thresh = (s32)x; - s32 sign1, isign2, a; - s32 *wimage = (s32 *)image; - int wsize = (width * height) >> 1; - thresh |= (thresh << 16); - for (i=0; i<wsize; i++){ - a = wimage[i]; - sign1 = _sign(a); - a ^= sign1; /* take abs */ - _decouple(&a); - a -= thresh; /* subtract threshold */ - isign2 = ~ _sign(a); - a &= isign2; /* zero thresh */ - _decouple(&a); - a += thresh & isign2; /* add threshold (if not zero thresholded)*/ - a ^= sign1; - wimage[i] = a; - } -} - -/* soft thresholding: x contains a positive unsigned short int */ -void pdp_imageproc_softthresh_process(void *x, u32 width, u32 height, s16 *image) -{ - int i; - s32 thresh = (s32)x; - s32 sign1, sign2, a; - s32 *wimage = (s32 *)image; - int wsize = (width * height) >> 1; - thresh |= thresh << 16; - for (i=0; i<wsize; i++){ - a = wimage[i]; - sign1 = _sign(a); - a ^= sign1; /* take abs */ - _decouple(&a); - a -= thresh; /* subtract threshold */ - sign2 = _sign(a); - a &= ~ sign2; /* zero thresh */ - _decouple(&a); - //a += thresh; /* add threshold */ - a ^= sign1; - wimage[i] = a; - - } - -} - - -/* turns an image into a positive andmask */ -void pdp_imageproc_ispositive_process(void *x, u32 width, u32 height, s16 *image) -{ - int i; - s32 *wimage = (s32 *)image; - int wsize = (width * height) >> 1; - for (i=0; i<wsize; i++){ - wimage[i] = ~_sign(wimage[i]); - } - -} - -/* get sign */ -void pdp_imageproc_sign_process(void *x, u32 width, u32 height, s16 *image) -{ - int i; - s32 *wimage = (s32 *)image; - int wsize = (width * height) >> 1; - for (i=0; i<wsize; i++){ - wimage[i] = _sign(wimage[i]) ^ 0x7fff7fff; - } - -} - -/* flip left <-> right */ -void pdp_imageproc_flip_lr_process(void *dummy, u32 width, u32 height, s16 *image) -{ - u32 y; - s16 tmp, *l, *r; - for (y=0; y<height; y++){ - l = image; - r = image + width - 1; - while (l < r){ - tmp = *l; - *l = *r; - *r = tmp; - l++; - r--; - } - image += width; - } - -} - -void pdp_llconv_flip_top_bottom(s16 *data, int width, int height, int pixelsize); - -void pdp_imageproc_flip_tb_process(void *dummy, u32 width, u32 height, s16 *image) -{ - pdp_llconv_flip_top_bottom(image, width, height, 2); -} - - -/* image processing dispatcher methods */ -/* if the first packet contains a nonzero channel mask, it will be used instead - of the one supplied as argument to the dispatcher functions. - the packet's channel mask will be reset to 0 */ - -void pdp_imageproc_dispatch_1buf(void (*process_routine)(void*, u32, u32, s16*), void *x, u32 chanmask, int packet0) -{ - t_pdp *header0; - t_image *image0; - s16 *idata0; - unsigned int w,h,d,plane_size,mask; - - /* if packet is not a valid image return without doing anything */ - if (!(pdp_packet_image_isvalid(packet0))) return; - - header0 = pdp_packet_header(packet0); - image0 = pdp_packet_image_info(packet0); - idata0 = pdp_packet_data (packet0); - - w = image0->width; - h = image0->height; - d = image0->depth; - plane_size = w*h; - - if (image0->chanmask) chanmask = image0->chanmask; - image0->chanmask = 0; - - - switch(image0->encoding){ - case PDP_IMAGE_GREY: - if (chanmask & 1) (*process_routine)(x, w, h, idata0); - break; - case PDP_IMAGE_YV12: - if (chanmask & 1) (*process_routine)(x, w, h, idata0); - idata0 += plane_size; - plane_size >>= 2; - w >>= 1; - h >>= 1; - if (chanmask & 2) (*process_routine)(x, w, h, idata0); - idata0 += plane_size; - if (chanmask & 4) (*process_routine)(x, w, h, idata0); - break; - case PDP_IMAGE_MCHP: - mask = 1; - while (d--){ - if (chanmask & mask) (*process_routine)(x, w, h, idata0); - idata0 += plane_size; - mask <<= 1; - } - break; - default: - break; - } -} - - -void pdp_imageproc_dispatch_2buf(void (*process_routine)(void*, u32, u32, s16*, s16 *), void *x, u32 chanmask, int packet0, int packet1) -{ - t_pdp *header0; - t_image *image0; - s16 *idata0, *idata1; - unsigned int w,h,d,plane_size,mask; - - /* if packets are not compatible images, return without doing anything */ - if (!(pdp_packet_image_compat(packet0, packet1))) return; - - header0 = pdp_packet_header(packet0); - image0 = pdp_packet_image_info(packet0); - idata0 = pdp_packet_data (packet0); - idata1 = pdp_packet_data (packet1); - - w = image0->width; - h = image0->height; - d = image0->depth; - plane_size = w*h; - - if (image0->chanmask) chanmask = image0->chanmask; - image0->chanmask = 0; - - switch(image0->encoding){ - case PDP_IMAGE_GREY: - if (chanmask & 1) (*process_routine)(x, w, h, idata0, idata1); - break; - case PDP_IMAGE_YV12: - if (chanmask & 1) (*process_routine)(x, w, h, idata0, idata1); - idata0 += plane_size; - idata1 += plane_size; - plane_size >>= 2; - w >>= 1; - h >>= 1; - if (chanmask & 2) (*process_routine)(x, w, h, idata0, idata1); - idata0 += plane_size; - idata1 += plane_size; - if (chanmask & 4) (*process_routine)(x, w, h, idata0, idata1); - break; - case PDP_IMAGE_MCHP: - mask = 1; - while (d--){ - if (chanmask & mask) (*process_routine)(x, w, h, idata0, idata1); - idata0 += plane_size; - idata1 += plane_size; - mask <<= 1; - } - break; - default: - break; - } -} -void pdp_imageproc_dispatch_3buf(void (*process_routine)(void*, u32, u32, s16*, s16 *, s16 *), void *x, u32 chanmask, int packet0, int packet1, int packet2) -{ - t_pdp *header0; - t_image *image0; - s16 *idata0, *idata1, *idata2; - unsigned int w,h,d,plane_size, mask; - - /* if packets are not compatible images, return without doing anything */ - if (!((pdp_packet_image_compat(packet0, packet1)) - &&(pdp_packet_image_compat(packet0, packet1)))) return; - - header0 = pdp_packet_header(packet0); - image0 = pdp_packet_image_info(packet0); - idata0 = pdp_packet_data (packet0); - idata1 = pdp_packet_data (packet1); - idata2 = pdp_packet_data (packet2); - - w = image0->width; - h = image0->height; - d = image0->depth; - plane_size = w*h; - - if (image0->chanmask) chanmask = image0->chanmask; - image0->chanmask = 0; - - switch(image0->encoding){ - case PDP_IMAGE_GREY: - if (chanmask & 1)(*process_routine)(x, w, h, idata0, idata1, idata2); - break; - case PDP_IMAGE_YV12: - if (chanmask & 1)(*process_routine)(x, w, h, idata0, idata1, idata2); - idata0 += plane_size; - idata1 += plane_size; - idata2 += plane_size; - plane_size >>= 2; - w >>= 1; - h >>= 1; - if (chanmask & 2)(*process_routine)(x, w, h, idata0, idata1, idata2); - idata0 += plane_size; - idata1 += plane_size; - idata2 += plane_size; - if (chanmask & 4)(*process_routine)(x, w, h, idata0, idata1, idata2); - break; - case PDP_IMAGE_MCHP: - mask = 1; - while (d--){ - if (chanmask & mask) (*process_routine)(x, w, h, idata0, idata1, idata2); - idata0 += plane_size; - idata1 += plane_size; - idata2 += plane_size; - mask <<= 1; - } - break; - default: - break; - } -} diff --git a/system/image/pdp_imageproc_mmx.c b/system/image/pdp_imageproc_mmx.c deleted file mode 100644 index b518aa2..0000000 --- a/system/image/pdp_imageproc_mmx.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Pure Data Packet. c wrapper for mmx image processing routines. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* this is a c wrapper around platform specific (mmx) code */ -#include <stdlib.h> -#include <math.h> -#include "pdp_mmx.h" -#include "pdp_imageproc.h" -#include "m_pd.h" - -/* pdp memory alloc/dealloc prototype */ -void *pdp_alloc(int size); -void pdp_dealloc(void *); - -// utility stuff -inline static s16 float2fixed(float f) -{ - if (f > 1) f = 1; - if (f < -1) f = -1; - f *= 0x7fff; - return (s16)f; -} - -inline static void setvec(s16 *v, float f) -{ - s16 a = float2fixed(f); - v[0] = a; - v[1] = a; - v[2] = a; - v[3] = a; -} - - - -// add two images -void pdp_imageproc_add_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - unsigned int totalnbpixels = width * height; - pixel_add_s16(image, image2, totalnbpixels>>2); -} - -// mul two images -void pdp_imageproc_mul_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - unsigned int totalnbpixels = width * height; - pixel_mul_s16(image, image2, totalnbpixels>>2); -} - -// mix 2 images -void *pdp_imageproc_mix_new(void){return pdp_alloc(8*sizeof(s16));} -void pdp_imageproc_mix_delete(void *x) {pdp_dealloc (x);} -void pdp_imageproc_mix_setleftgain(void *x, float gain){setvec((s16 *)x, gain);} -void pdp_imageproc_mix_setrightgain(void *x, float gain){setvec((s16 *)x + 4, gain);} -void pdp_imageproc_mix_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - s16 *d = (s16 *)x; - unsigned int totalnbpixels = width * height; - pixel_mix_s16(image, image2, totalnbpixels>>2, d, d+4); -} - - -// random mix 2 images -void *pdp_imageproc_randmix_new(void){return pdp_alloc(8*sizeof(s16));} -void pdp_imageproc_randmix_delete(void *x) {pdp_dealloc (x);} -void pdp_imageproc_randmix_setthreshold(void *x, float threshold){setvec((s16 *)x, 2*threshold-1);} -void pdp_imageproc_randmix_setseed(void *x, float seed) -{ - s16 *d = (s16 *)x; - srandom((u32)seed); - d[4] = (s16)random(); - d[5] = (s16)random(); - d[6] = (s16)random(); - d[7] = (s16)random(); - -} -void pdp_imageproc_randmix_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - s16 *d = (s16 *)x; - unsigned int totalnbpixels = width * height; - pixel_randmix_s16(image, image2, totalnbpixels>>2, d+4, d); -} - - -// 3x1 or 1x3 in place convolution -// orientation -typedef struct -{ - s16 min1[4]; - s16 zero[4]; - s16 plus1[4]; - s16 border[4]; - u32 orientation; - u32 nbpasses; -} t_conv; -void *pdp_imageproc_conv_new(void){return(pdp_alloc(sizeof(t_conv)));} -void pdp_imageproc_conv_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_conv_setmin1(void *x, float val){setvec(((t_conv *)x)->min1, val);} -void pdp_imageproc_conv_setzero(void *x, float val){setvec(((t_conv *)x)->zero, val);} -void pdp_imageproc_conv_setplus1(void *x, float val){setvec(((t_conv *)x)->plus1, val);} -void pdp_imageproc_conv_setbordercolor(void *x, float val){setvec(((t_conv *)x)->border, val);} -void pdp_imageproc_conv_setorientation(void *x, u32 val){((t_conv *)x)->orientation = val;} -void pdp_imageproc_conv_setnbpasses(void *x, u32 val){((t_conv *)x)->nbpasses = val;} -void pdp_imageproc_conv_process(void *x, u32 width, u32 height, s16 *image) - -{ - t_conv *d = (t_conv *)x; - - u32 orientation = d->orientation; - u32 nbp = d->nbpasses; - u32 i,j; - - if (orientation == PDP_IMAGEPROC_CONV_HORIZONTAL) - { - for(i=0; i<width*height; i+=width) - for (j=0; j<nbp; j++) - pixel_conv_hor_s16(image+i, width>>2, d->border, d->min1); - } - - else - { - for (j=0; j<nbp; j++) - for(i=0; i<width; i +=4) pixel_conv_ver_s16(image+i, height, width, d->border, d->min1); - } - - - -} - -// apply a gain to an image -void *pdp_imageproc_gain_new(void){return(pdp_alloc(8*sizeof(s16)));} -void pdp_imageproc_gain_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_gain_setgain(void *x, float gain) -{ - /* convert float to s16 + shift */ - s16 *d = (s16 *)x; - s16 g; - int i; - float sign; - int shift = 0; - - sign = (gain < 0) ? -1 : 1; - gain *= sign; - - /* max shift = 16 */ - for(i=0; i<=16; i++){ - if (gain < 0x4000){ - gain *= 2; - shift++; - } - else break; - } - - gain *= sign; - g = (s16) gain; - - //g = 0x4000; - //shift = 14; - - d[0]=g; - d[1]=g; - d[2]=g; - d[3]=g; - d[4]=(s16)shift; - d[5]=0; - d[6]=0; - d[7]=0; -} -void pdp_imageproc_gain_process(void *x, u32 width, u32 height, s16 *image) -{ - s16 *d = (s16 *)x; - pixel_gain_s16(image, (width*height)>>2, d, (u64 *)(d+4)); -} - -// colour rotation for 2 colour planes -void *pdp_imageproc_crot2d_new(void){return pdp_alloc(16*sizeof(s16));} -void pdp_imageproc_crot2d_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_crot2d_setmatrix(void *x, float *matrix) -{ - s16 *d = (s16 *)x; - setvec(d, matrix[0]); - setvec(d+4, matrix[1]); - setvec(d+8, matrix[2]); - setvec(d+12, matrix[3]); -} -void pdp_imageproc_crot2d_process(void *x, s16 *image, u32 width, u32 height) -{ - s16 *d = (s16 *)x; - pixel_crot2d_s16(image, width*height >> 2, d); -} - -// biquad and biquad time -typedef struct -{ - s16 ma1[4]; - s16 ma2[4]; - s16 b0[4]; - s16 b1[4]; - s16 b2[4]; - s16 u0[4]; - s16 u1[4]; - s16 u0_save[4]; - s16 u1_save[4]; - u32 nbpasses; - u32 direction; -} t_bq; - -void *pdp_imageproc_bq_new(void){return pdp_alloc(sizeof(t_bq));} -void pdp_imageproc_bq_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_bq_setcoef(void *x, float *coef) // a0,-a1,-a2,b0,b1,b2,u0,u1 -{ - t_bq *d = (t_bq *)x; - float ia0 = 1.0f / coef[0]; - - /* all coefs are s1.14 fixed point */ - /* representing values -2 < x < 2 */ - /* so scale down before using the ordinary s0.15 float->fixed routine */ - - ia0 *= 0.5f; - - // coef - setvec(d->ma1, ia0*coef[1]); - setvec(d->ma2, ia0*coef[2]); - setvec(d->b0, ia0*coef[3]); - setvec(d->b1, ia0*coef[4]); - setvec(d->b2, ia0*coef[5]); - - // state to reset too - setvec(d->u0_save, coef[6]); - setvec(d->u1_save, coef[7]); - -} -void pdp_imageproc_bq_setnbpasses(void *x, u32 nbpasses){((t_bq *)x)->nbpasses = nbpasses;} -void pdp_imageproc_bq_setdirection(void *x, u32 direction){((t_bq *)x)->direction = direction;} -void pdp_imageproc_bq_process(void *x, u32 width, u32 height, s16* image); - - -void pdp_imageproc_bqt_process(void *x, u32 width, u32 height, s16 *image, s16 *state0, s16 *state1) -{ - s16 *d = (s16 *)x; - pixel_biquad_time_s16(image, state0, state1, d, (width*height)>>2); -} - -void pdp_imageproc_bq_process(void *x, u32 width, u32 height, s16 *image) -{ - t_bq *d = (t_bq *)x; - s16 *c = d->ma1; /* coefs */ - s16 *s = d->u0; /* state */ - u32 direction = d->direction; - u32 nbp = d->nbpasses; - unsigned int i,j; - - - - /* VERTICAL */ - - if ((direction & PDP_IMAGEPROC_BIQUAD_TOP2BOTTOM) - && (direction & PDP_IMAGEPROC_BIQUAD_BOTTOM2TOP)){ - - for(i=0; i<width; i +=4){ - for (j=0; j<nbp; j++){ - pixel_biquad_vertb_s16(image+i, height>>2, width, c, s); - pixel_biquad_verbt_s16(image+i, height>>2, width, c, s); - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_TOP2BOTTOM){ - for(i=0; i<width; i +=4){ - for (j=0; j<nbp; j++){ - pixel_biquad_vertb_s16(image+i, height>>2, width, c, s); - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_BOTTOM2TOP){ - for(i=0; i<width; i +=4){ - for (j=0; j<nbp; j++){ - pixel_biquad_verbt_s16(image+i, height>>2, width, c, s); - } - } - } - - /* HORIZONTAL */ - - if ((direction & PDP_IMAGEPROC_BIQUAD_LEFT2RIGHT) - && (direction & PDP_IMAGEPROC_BIQUAD_RIGHT2LEFT)){ - - for(i=0; i<(width*height); i +=(width<<2)){ - for (j=0; j<nbp; j++){ - pixel_biquad_horlr_s16(image+i, width>>2, width, c, s); - pixel_biquad_horrl_s16(image+i, width>>2, width, c, s); - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_LEFT2RIGHT){ - for(i=0; i<(width*height); i +=(width<<2)){ - for (j=0; j<nbp; j++){ - pixel_biquad_horlr_s16(image+i, width>>2, width, c, s); - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_RIGHT2LEFT){ - for(i=0; i<(width*height); i +=(width<<2)){ - for (j=0; j<nbp; j++){ - pixel_biquad_horrl_s16(image+i, width>>2, width, c, s); - } - } - } - -} - -// produce a random image -// note: random number generator can be platform specific -// however, it should be seeded. (same seed produces the same result) -void *pdp_imageproc_random_new(void){return pdp_alloc(4*sizeof(s16));} -void pdp_imageproc_random_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_random_setseed(void *x, float seed) -{ - s16 *d = (s16 *)x; - srandom((u32)seed); - d[0] = (s16)random(); - d[1] = (s16)random(); - d[2] = (s16)random(); - d[3] = (s16)random(); - -} -void pdp_imageproc_random_process(void *x, u32 width, u32 height, s16 *image) -{ - s16 *d = (s16 *)x; - unsigned int totalnbpixels = width * height; - pixel_rand_s16(image, totalnbpixels>>2, d); -} - - -/* resampling stuff - this is quite a zoo of data structures - the major point is this: the resampler mmx code is shared for all resampling code - it uses data specified in t_resample_cbrd (Cooked Bilinear Resampler Data) - - then the there are several feeder algorithms. one is the linear mapper. it's - data is specified in t_resample_clrd (Cooked Linear Remapper Data) - - for each feeder algorithm, there are several high level algorithms. like zoom, - rotate, ... -*/ - -typedef struct -{ - u32 lineoffset; - s16 *image; - u32 width; - u32 height; - -} t_resample_id; // Image Data - -/* initialize image meta data (dimensions + location) */ -static void pdp_imageproc_resample_init_id(t_resample_id *x, u32 offset, s16* image, u32 w, u32 h) -{ - x->lineoffset = offset; - x->image = image; - x->width = w; - x->height = h; -} - -// mmx resampling source image resampling data + coefs -typedef struct -{ - // vector data for resampling routine (resampling computation) - u8 reserved[0x60]; //internal data - s16 *address[2]; //64 bit splatted offset address - s16 twowidthm1[4]; //64 bit splatted 2*(width-1) - s16 twoheightm1[4]; //64 bit splatted 2*(height-1) - s16 lineoffset[4]; //64 bit splatted line offset in pixels - -} t_resample_cid; // Cooked Image Data - -/* convert image meta data into a cooked format used by the resampler routine */ -static void pdp_imageproc_resample_init_cid(t_resample_cid *r, t_resample_id *i) -{ - u32 twowm1 = (i->width-1)<<1; - u32 twohm1 = (i->height-1)<<1; - r->address[0] = i->image; - r->address[1] = i->image; - r->twowidthm1[0] = twowm1; - r->twowidthm1[1] = twowm1; - r->twowidthm1[2] = twowm1; - r->twowidthm1[3] = twowm1; - r->twoheightm1[0] = twohm1; - r->twoheightm1[1] = twohm1; - r->twoheightm1[2] = twohm1; - r->twoheightm1[3] = twohm1; - r->lineoffset[0] = i->lineoffset; - r->lineoffset[1] = i->lineoffset; - r->lineoffset[2] = i->lineoffset; - r->lineoffset[3] = i->lineoffset; -} - -// linear mapping data struct (zoom, scale, rotate, shear, ...) -typedef struct -{ - s32 rowstatex[2]; // row state x coord - s32 rowstatey[2]; // row state y coord - s32 colstatex[2]; // column state x coord - s32 colstatey[2]; // column state y coord - s32 rowincx[2]; // row inc vector x coord - s32 rowincy[2]; // row inc vector y coord - s32 colincx[2]; // column inc vector x coord - s32 colincy[2]; // column inc vector y coord -} t_resample_clmd; // Cooked Linear Mapping Data - -/* convert incremental linear remapping vectors to internal cooked format */ -static void pdp_imageproc_resample_cookedlinmap_init(t_resample_clmd *l, s32 sx, s32 sy, s32 rix, s32 riy, s32 cix, s32 ciy) -{ - l->colstatex[0] = l->rowstatex[0] = sx; - l->colstatex[1] = l->rowstatex[1] = sx + rix; - l->colstatey[0] = l->rowstatey[0] = sy; - l->colstatey[1] = l->rowstatey[1] = sy + riy; - l->rowincx[0] = rix << 1; - l->rowincx[1] = rix << 1; - l->rowincy[0] = riy << 1; - l->rowincy[1] = riy << 1; - l->colincx[0] = cix; - l->colincx[1] = cix; - l->colincy[0] = ciy; - l->colincy[1] = ciy; -} - - -/* this struct contains all the data necessary for - bilin interpolation from src -> dst image - (src can be == dst) */ -typedef struct -{ - t_resample_cid csrc; //cooked src image meta data for bilinear interpolator - t_resample_id src; //src image meta - t_resample_id dst; //dst image meta -} t_resample_cbrd; //Bilinear Resampler Data - - -/* this struct contains high level zoom parameters, - all image relative */ -typedef struct -{ - float centerx; - float centery; - float zoomx; - float zoomy; - float angle; -} t_resample_zrd; - - -/* convert floating point center and zoom data to incremental linear remapping vectors */ -static void pdp_imageproc_resample_clmd_init_from_id_zrd(t_resample_clmd *l, t_resample_id *i, t_resample_zrd *z) -{ - double izx = 1.0f / (z->zoomx); - double izy = 1.0f / (z->zoomy); - double scale = (double)0xffffffff; - double scalew = scale / ((double)(i->width - 1)); - double scaleh = scale / ((double)(i->height - 1)); - double cx = ((double)z->centerx) * ((double)(i->width - 1)); - double cy = ((double)z->centery) * ((double)(i->height - 1)); - double angle = z->angle * (-M_PI / 180.0); - double c = cos(angle); - double s = sin(angle); - - /* affine x, y mappings in screen coordinates */ - double mapx(double x, double y){return cx + izx * ( c * (x-cx) + s * (y-cy));} - double mapy(double x, double y){return cy + izy * (-s * (x-cx) + c * (y-cy));} - - u32 tl_x = (u32)(scalew * mapx(0,0)); - u32 tl_y = (u32)(scaleh * mapy(0,0)); - - - u32 row_inc_x = (u32)(scalew * (mapx(1,0)-mapx(0,0))); - u32 row_inc_y = (u32)(scaleh * (mapy(1,0)-mapy(0,0))); - u32 col_inc_x = (u32)(scalew * (mapx(0,1)-mapx(0,0))); - u32 col_inc_y = (u32)(scaleh * (mapy(0,1)-mapy(0,0))); - - - pdp_imageproc_resample_cookedlinmap_init(l, tl_x, tl_y, row_inc_x, row_inc_y, col_inc_x, col_inc_y); -} - -/* this struct contains all data for the zoom object */ -typedef struct -{ - t_resample_cbrd cbrd; // Bilinear Resampler Data - t_resample_clmd clmd; // Cooked Linear Mapping data - t_resample_zrd zrd; // Zoom / Rotate Data -} t_resample_zoom_rotate; - -// zoom + rotate -void *pdp_imageproc_resample_affinemap_new(void) -{ - t_resample_zoom_rotate *z = (t_resample_zoom_rotate *)pdp_alloc(sizeof(t_resample_zoom_rotate)); - z->zrd.centerx = 0.5; - z->zrd.centery = 0.5; - z->zrd.zoomx = 1.0; - z->zrd.zoomy = 1.0; - z->zrd.angle = 0.0f; - return (void *)z; -} -void pdp_imageproc_resample_affinemap_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_resample_affinemap_setcenterx(void *x, float f){((t_resample_zoom_rotate *)x)->zrd.centerx = f;} -void pdp_imageproc_resample_affinemap_setcentery(void *x, float f){((t_resample_zoom_rotate *)x)->zrd.centery = f;} -void pdp_imageproc_resample_affinemap_setzoomx(void *x, float f){((t_resample_zoom_rotate *)x)->zrd.zoomx = f;} -void pdp_imageproc_resample_affinemap_setzoomy(void *x, float f){((t_resample_zoom_rotate *)x)->zrd.zoomy = f;} -void pdp_imageproc_resample_affinemap_setangle(void *x, float f){((t_resample_zoom_rotate *)x)->zrd.angle = f;} -void pdp_imageproc_resample_affinemap_process(void *x, u32 width, u32 height, s16 *srcimage, s16 *dstimage) -{ - t_resample_zoom_rotate *z = (t_resample_zoom_rotate *)x; - - /* setup resampler image meta data */ - pdp_imageproc_resample_init_id(&(z->cbrd.src), width, srcimage, width, height); - pdp_imageproc_resample_init_id(&(z->cbrd.dst), width, dstimage, width, height); - pdp_imageproc_resample_init_cid(&(z->cbrd.csrc),&(z->cbrd.src)); - - /* setup linmap data from zoom_rotate parameters */ - pdp_imageproc_resample_clmd_init_from_id_zrd(&(z->clmd), &(z->cbrd.src), &(z->zrd)); - - - /* call assembler routine */ - pixel_resample_linmap_s16(z); -} - - - -// polynomials - - -typedef struct -{ - u32 order; - u32 nbpasses; - s16 coefs[0]; -} t_cheby; - -void *pdp_imageproc_cheby_new(int order) -{ - t_cheby *z; - int i; - if (order < 2) order = 2; - z = (t_cheby *)pdp_alloc(sizeof(t_cheby) + (order + 1) * sizeof(s16[4])); - z->order = order; - setvec(z->coefs + 0*4, 0); - setvec(z->coefs + 1*4, 0.25); - for (i=2; i<=order; i++) setvec(z->coefs + i*4, 0); - - return z; -} -void pdp_imageproc_cheby_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_cheby_setcoef(void *x, u32 n, float f) -{ - t_cheby *z = (t_cheby *)x; - if (n <= z->order){ - setvec(z->coefs + n*4, f * 0.25); // coefs are in s2.13 format - } -} -void pdp_imageproc_cheby_setnbpasses(void *x, u32 n){((t_cheby *)x)->nbpasses = n;} - -void pdp_imageproc_cheby_process(void *x, u32 width, u32 height, s16 *image) -{ - t_cheby *z = (t_cheby *)x; - u32 iterations = z->nbpasses; - u32 i,j; - for (j=0; j < (height*width); j += width) - for (i=0; i<iterations; i++) - pixel_cheby_s16_3plus(image+j, width>>2, z->order+1, z->coefs); - - //pixel_cheby_s16_3plus(image, (width*height)>>2, z->order+1, z->coefs); -} diff --git a/system/image/pdp_imageproc_portable.c b/system/image/pdp_imageproc_portable.c deleted file mode 100644 index 53f195f..0000000 --- a/system/image/pdp_imageproc_portable.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Pure Data Packet. portable image processing routines. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - - -#include <stdlib.h> -#include <stdio.h> -#include <math.h> -#include "pdp_imageproc.h" - -/* pdp memory alloc/dealloc prototype */ -void *pdp_alloc(int size); -void pdp_dealloc(void *); - - -// utility stuff -inline static s32 float2fixed(float f) -{ - if (f > 1) f = 1; - if (f < -1) f = -1; - f *= 0x7fff; - return (s32)f; -} - - - -#define CLAMP16(x) (((x) > 0x7fff) ? 0x7fff : (((x) < -0x7fff) ? -0x7fff : (x))) - -// add two images -void pdp_imageproc_add_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - int a, b; - unsigned int i; - for (i=0; i<width*height; i++){ - a = (int)image[i]; - b = (int)image2[i]; - image[i] = (s16)(CLAMP16(a+b)); - } - -} - -// mul two images -void pdp_imageproc_mul_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - int a, b; - unsigned int i; - for (i=0; i<width*height; i++){ - a = (int)image[i]; - b = (int)image2[i]; - image[i] = (s16)((a*b)>>15); - } - -} - -// mix 2 images -void *pdp_imageproc_mix_new(void){return pdp_alloc(2*sizeof(s32));} -void pdp_imageproc_mix_delete(void *x) {pdp_dealloc (x);} -void pdp_imageproc_mix_setleftgain(void *x, float gain) -{ - s32 *d = (s32 *)x; - d[0] = float2fixed(gain); -} -void pdp_imageproc_mix_setrightgain(void *x, float gain) -{ - s32 *d = (s32 *)x; - d[1] = float2fixed(gain); -} -void pdp_imageproc_mix_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - s32 *d = (s32 *)x; - u32 i; - s32 a,b; - - for(i=0; i<width*height; i++){ - a = (s32)image[i]; - b = (s32)image2[i]; - a = (a*d[0] + b*d[1]) >> 15; - image[i] = (s16)CLAMP16(a); - } - -} - - -// random mix 2 images -void *pdp_imageproc_randmix_new(void){return pdp_alloc(2*sizeof(s32));;} -void pdp_imageproc_randmix_delete(void *x) {pdp_dealloc(x);} -void pdp_imageproc_randmix_setthreshold(void *x, float threshold) -{ - s32 *d = (s32 *)x; - if (threshold > 1.0f) threshold = 1.0f; - if (threshold < 0.0f) threshold = 0.0f; - d[0] = float2fixed(threshold); -} -void pdp_imageproc_randmix_setseed(void *x, float seed) -{ - s32 *d = (s32 *)x; - d[1] = float2fixed(seed); -} -void pdp_imageproc_randmix_process(void *x, u32 width, u32 height, s16 *image, s16 *image2) -{ - s32 *d = (s32 *)x; - u32 i; - s16 r; - srandom((u32)d[1]); - - - for(i=0; i<width*height; i++){ - // get a random val between 0 and 0x7fff - r = (s16)(random() & 0x7fff); - if (r < d[0]) image[i] = image2[i]; - } -} - - -// 3x1 or 1x3 in place convolution -// orientation -void *pdp_imageproc_conv_new(void){return(pdp_alloc(6*sizeof(s32)));} -void pdp_imageproc_conv_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_conv_setmin1(void *x, float val) -{ - s32 *d = (s32 *)x; - d[0] = float2fixed(val); -} -void pdp_imageproc_conv_setzero(void *x, float val) -{ - s32 *d = (s32 *)x; - d[1] = float2fixed(val); -} -void pdp_imageproc_conv_setplus1(void *x, float val) -{ - s32 *d = (s32 *)x; - d[2] = float2fixed(val); -} -void pdp_imageproc_conv_setbordercolor(void *x, float val) -{ - s32 *d = (s32 *)x; - d[3] = float2fixed(val); -} -void pdp_imageproc_conv_setorientation(void *x, u32 val){((u32 *)x)[4] = val;} -void pdp_imageproc_conv_setnbpasses(void *x, u32 val){((u32 *)x)[5] = val;} - -static inline void pdp_imageproc_conv_scanline(void *x, s16 *data, u32 count, s32 stride) -{ - s32 *d = (s32 *)x; - s32 a,b,c,r; - u32 i; - - a = d[3]; //border - b = data[0]; - c = data[stride]; - - for(i = 0; i < count-2; i++){ - r = a*d[0] + b*d[1] + c*d[2]; - a = data[0]; - b = data[stride]; - c = data[stride<<1]; - data[0] = (s16)CLAMP16(r>>15); - data += stride; - } - r = a*d[0] + b*d[1] + c*d[2]; - a = data[0]; - b = data[stride]; - c = d[3]; //border - data[0] = (s16)CLAMP16(r>>15); - r = a*d[0] + b*d[1] + c*d[2]; - data[stride] = (s16)CLAMP16(r>>15); - -} - -void pdp_imageproc_conv_process(void *x, u32 width, u32 height, s16 *image) -{ - s32 *d = (s32 *)x; - u32 i, j; - u32 orientation = d[4]; - u32 nbp = d[5]; - if (orientation == PDP_IMAGEPROC_CONV_HORIZONTAL){ - for(i=0; i<width*height; i+=width) - for(j=0; j<nbp; j++) - pdp_imageproc_conv_scanline(x, image+i, width, 1); - - } - - if (orientation == PDP_IMAGEPROC_CONV_VERTICAL){ - for(i=0; i<width; i++) - for(j=0; j<nbp; j++) - pdp_imageproc_conv_scanline(x, image+i, height, width); - - } - - - - -} - -// apply a gain to an image -void *pdp_imageproc_gain_new(void){return(pdp_alloc(2*sizeof(s32)));} -void pdp_imageproc_gain_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_gain_setgain(void *x, float gain) -{ - /* convert float to s16 + shift */ - s32 *d = (s32 *)x; - s32 g; - int i; - float sign; - s32 shift = 0; - - sign = (gain < 0) ? -1 : 1; - gain *= sign; - - /* max shift = 16 */ - for(i=0; i<=16; i++){ - if (gain < 0x4000){ - gain *= 2; - shift++; - } - else break; - } - - gain *= sign; - g = (s32) gain; - - //g = 0x4000; - //shift = 14; - - d[0]=g; - d[1]=shift; -} -void pdp_imageproc_gain_process(void *x, u32 width, u32 height, s16 *image) -{ - s32 *d = (s32 *)x; - s32 a; - u32 i; - for (i=0; i<width*height; i++){ - a = (s32)image[i]; - image[i] = (s16)(CLAMP16((a * d[0]) >> d[1])); - } -} - -// colour rotation for 2 colour planes -void *pdp_imageproc_crot2d_new(void){return pdp_alloc(4*sizeof(s32));} -void pdp_imageproc_crot2d_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_crot2d_setmatrix(void *x, float *matrix) -{ - s32 *d = (s32 *)x; - d[0] = float2fixed(matrix[0]); - d[1] = float2fixed(matrix[1]); - d[2] = float2fixed(matrix[2]); - d[3] = float2fixed(matrix[3]); - -} -void pdp_imageproc_crot2d_process(void *x, s16 *image, u32 width, u32 height) -{ - s32 *d = (s32 *)x; - u32 i,j; - s32 a1,a2,c1,c2; - - for(i=0, j=width*height; i<width*height; i++, j++){ - c1 = (s32)image[i]; - c2 = (s32)image[j]; - - a1 = d[0] * c1; - a2 = d[1] * c1; - a1+= d[2] * c2; - a2+= d[3] * c2; - - a1 >>= 15; - a2 >>= 15; - - image[i] = (s16)CLAMP16(a1); - image[j] = (s16)CLAMP16(a2); - } -} - -// biquad and biquad time -typedef struct -{ - s32 ma1; - s32 ma2; - s32 b0; - s32 b1; - s32 b2; - - s32 u0; - s32 u1; - - s32 u0_save; - s32 u1_save; - - u32 nbpasses; - u32 direction; -} t_bq; -void *pdp_imageproc_bq_new(void){return pdp_alloc(sizeof(t_bq));} -void pdp_imageproc_bq_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_bq_setnbpasses(void *x, u32 i){((t_bq *)x)->nbpasses = i;} -void pdp_imageproc_bq_setdirection(void *x, u32 i){((t_bq *)x)->direction = i;} -void pdp_imageproc_bq_setcoef(void *x, float *coef) // a0,-a1,-a2,b0,b1,b2,u0,u1 -{ - s32 *d = (s32 *)x; - float ia0 = 1.0f / coef[0]; - - /* all coefs are s1.14 fixed point */ - /* representing values -2 < x < 2 */ - /* so scale down before using the ordinary s0.15 float->fixed routine */ - - ia0 *= 0.5f; - - // coef - d[0] = float2fixed(ia0*coef[1]); // -a1 - d[1] = float2fixed(ia0*coef[2]); // -a2 - d[2] = float2fixed(ia0*coef[3]); // b0 - d[3] = float2fixed(ia0*coef[4]); // b1 - d[4] = float2fixed(ia0*coef[5]); // b2 - - - // state to reset too - d[5] = float2fixed(coef[6]); - d[6] = float2fixed(coef[7]); - -} - -#define A1 d[0] -#define A2 d[1] -#define B0 d[2] -#define B1 d[3] -#define B2 d[4] -/* - # DIRECT FORM II BIQUAD (from pixel_biquad_s16.s) - # - # y[k] = b0 * x[k] + u1[k-1] - # u1[k] = b1 * x[k] + u2[k-1] - a1 * y[k] - # u2[k] = b2 * x[k] - a2 * y[k] -*/ - -/* remark A1 and A2 are already negated) */ - - -static inline void pdp_imageproc_bq_scanline(void *x, s16 *data, u32 count, s32 stride) -{ - - s32 *d = (s32 *)x; - s32 u1,u2, xx, yy; - - u32 i; - - u1 = d[7]; - u2 = d[8]; - - for(i = 0; i < count; i++){ - - xx = (s32)data[0]; - - yy = ((B0 * xx)>>14) + u1; - u1 = ((B1 * xx)>>14) + u2 + ((A1 * yy)>>14); - u2 = ((B2 * xx)>>14) + ((A2 * yy)>>14); - - data[0] = (s16)CLAMP16(yy); - - data += stride; - - } - - d[7] = u1; - d[8] = u2; - -} - -void pdp_imageproc_bqt_process(void *x, u32 width, u32 height, s16 *image, s16 *state1, s16 *state2) -{ - s32 *d = (s32 *)x; - u32 i; - s32 u1, u2, xx, yy; - - for (i=0; i<width*height; i++){ - - xx = (s32)image[i]; - u1 = (s32)state1[i]; - u2 = (s32)state2[i]; - - yy = ((B0 * xx)>>14) + u1; - u1 = ((B1 * xx)>>14) + u2 + ((A1 * yy)>>14); - u2 = ((B2 * xx)>>14) + ((A2 * yy)>>14); - - image[i] = (s16)CLAMP16(yy); - state1[i] = (s16)CLAMP16(u1); - state2[i] = (s16)CLAMP16(u2); - } - - -} - -void pdp_imageproc_bq_process(void *x, u32 width, u32 height, s16 *data) -{ - s32 *d = (s32 *)x; - - u32 nbp = d[9]; - u32 direction = d[10]; - unsigned int i,j, offset; - - - /* VERTICAL */ - offset = (height-1)*width; - - if ((direction & PDP_IMAGEPROC_BIQUAD_TOP2BOTTOM) - && (direction & PDP_IMAGEPROC_BIQUAD_BOTTOM2TOP)){ - - for(i=0; i<width; i++){ - for (j=0; j<nbp; j++){ - pdp_imageproc_bq_scanline(x, data+i, height, width); //T->B - pdp_imageproc_bq_scanline(x, data+offset+i, height, -width); //B->T - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_TOP2BOTTOM){ - for(i=0; i<width; i++){ - for (j=0; j<nbp; j++){ - pdp_imageproc_bq_scanline(x, data+i, height, width); //T->B - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_BOTTOM2TOP){ - for(i=0; i<width; i++){ - for (j=0; j<nbp; j++){ - pdp_imageproc_bq_scanline(x, data+offset+i, height, -width); //B->T - } - } - } - - /* HORIZONTAL */ - - offset = width-1; - if ((direction & PDP_IMAGEPROC_BIQUAD_LEFT2RIGHT) - && (direction & PDP_IMAGEPROC_BIQUAD_RIGHT2LEFT)){ - - for(i=0; i<(width*height); i += width){ - for (j=0; j<nbp; j++){ - pdp_imageproc_bq_scanline(x, data+i, width, 1); //L->R - pdp_imageproc_bq_scanline(x, data+offset+i, width, -1); //R->L - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_LEFT2RIGHT){ - for(i=0; i<(width*height); i += width){ - for (j=0; j<nbp; j++){ - pdp_imageproc_bq_scanline(x, data+i, width, 1); //L->R - } - } - } - - else if (direction & PDP_IMAGEPROC_BIQUAD_RIGHT2LEFT){ - for(i=0; i<(width*height); i += width){ - for (j=0; j<nbp; j++){ - pdp_imageproc_bq_scanline(x, data+offset+i, width, -1); //R->L - - } - } - } - -} - -// produce a random image -// note: random number generator can be platform specific -// however, it should be seeded. (same seed produces the same result) -void *pdp_imageproc_random_new(void){return pdp_alloc(sizeof(s32));} -void pdp_imageproc_random_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_random_setseed(void *x, float seed) -{ - float *f = (float *)x; - u32 *d = (u32 *)x; - f[0] = seed; - srandom(d[0]); -} - -void pdp_imageproc_random_process(void *x, u32 width, u32 height, short int *image) -{ - s32 *d = (u32 *)x; - u32 i; - s32 r; - srandom(d[0]); - for (i=0; i<(width*height); i++) { - r = random(); - image[i] = r; - } - d[0] = random(); -} - - - -/* resampling code */ -// zoom + rotate - -/* bilinear resampling core routine */ -/* virtual coordinates are the lowest 16 bits in virt_x and virt_y*/ -static inline s32 pdp_resample_bilin(s16 *image, s32 width, s32 height, s32 virt_x, s32 virt_y) -{ - - s32 fp_x, fp_y, frac_x, frac_y, f, offset, r_1, r_2; - - //virt_x &= 0xffff; - //virt_y &= 0xffff; - - fp_x = virt_x * (width - 1); - fp_y = virt_y * (height - 1); - - frac_x = fp_x & (0xffff); - frac_y = fp_y & (0xffff); - - offset = (fp_x >> 16) + (fp_y >> 16) * width; - image += offset; - - f = 0x10000 - frac_x; - - r_1 = ((f * (s32)(image[0]) + frac_x * (s32)(image[1])))>>16; - - image += width; - - r_2 = ((f * (s32)(image[0]) + frac_x * (s32)(image[1])))>>16; - - f = 0x10000 - frac_y; - - return ((f * r_1 + frac_y * r_2)>>16); - -} - -typedef struct -{ - float centerx; - float centery; - float zoomx; - float zoomy; - float angle; -} t_affine_map; - - -void *pdp_imageproc_resample_affinemap_new(void) -{ - - t_affine_map *a = (t_affine_map *)pdp_alloc(sizeof(t_affine_map)); - a->centerx = 0.5; - a->centery = 0.5; - a->zoomx = 1.0; - a->zoomy = 1.0; - a->angle = 0.0f; - return (void *)a; -} - -void pdp_imageproc_resample_affinemap_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_resample_affinemap_setcenterx(void *x, float f){((t_affine_map *)x)->centerx = f;} -void pdp_imageproc_resample_affinemap_setcentery(void *x, float f){((t_affine_map *)x)->centery = f;} -void pdp_imageproc_resample_affinemap_setzoomx(void *x, float f){((t_affine_map *)x)->zoomx = f;} -void pdp_imageproc_resample_affinemap_setzoomy(void *x, float f){((t_affine_map *)x)->zoomy = f;} -void pdp_imageproc_resample_affinemap_setangle(void *x, float f){((t_affine_map *)x)->angle = f;} -void pdp_imageproc_resample_affinemap_process(void *x, u32 width, u32 height, s16 *srcimage, s16 *dstimage) -{ - t_affine_map *a = (t_affine_map *)x; - double izx = 1.0f / (a->zoomx); - double izy = 1.0f / (a->zoomy); - double scale = (double)0xffffffff; - double scalew = scale / ((double)(width - 1)); - double scaleh = scale / ((double)(height - 1)); - double cx = ((double)a->centerx) * ((double)(width - 1)); - double cy = ((double)a->centery) * ((double)(height - 1)); - double angle = a->angle * (-M_PI / 180.0); - double c = cos(angle); - double s = sin(angle); - - /* affine x, y mappings in screen coordinates */ - double mapx(double x, double y){return cx + izx * ( c * (x-cx) + s * (y-cy));} - double mapy(double x, double y){return cy + izy * (-s * (x-cx) + c * (y-cy));} - - u32 colstate_x = (u32)(scalew * mapx(0,0)); - u32 colstate_y = (u32)(scaleh * mapy(0,0)); - u32 rowstate_x = colstate_x; - u32 rowstate_y = colstate_y; - - u32 row_inc_x = (u32)(scalew * (mapx(1,0)-mapx(0,0))); - u32 row_inc_y = (u32)(scaleh * (mapy(1,0)-mapy(0,0))); - u32 col_inc_x = (u32)(scalew * (mapx(0,1)-mapx(0,0))); - u32 col_inc_y = (u32)(scaleh * (mapy(0,1)-mapy(0,0))); - - u32 i,j; - - for (j=0; j<height; j++){ - for (i=0; i<width; i++){ - *dstimage++ = pdp_resample_bilin(srcimage, width, height, rowstate_x>>16, rowstate_y>>16); - rowstate_x += row_inc_x; - rowstate_y += row_inc_y; - } - colstate_x += col_inc_x; - colstate_y += col_inc_y; - rowstate_x = colstate_x; - rowstate_y = colstate_y; - } - -} - - - - - -// polynomials - - - - -typedef struct -{ - u32 order; - u32 nbpasses; - s32 coefs[0]; -} t_cheby; - -void *pdp_imageproc_cheby_new(int order) -{ - t_cheby *z; - int i; - if (order < 2) order = 2; - z = (t_cheby *)pdp_alloc(sizeof(t_cheby) + (order + 1) * sizeof(s32)); - z->order = order; - z->coefs[0] = 0; - z->coefs[1] = 0x7fff; - for (i=2; i<=order; i++) z->coefs[i] = 0; - return z; -} -void pdp_imageproc_cheby_delete(void *x){pdp_dealloc(x);} -void pdp_imageproc_cheby_setnbpasses(void *x, u32 n){((t_cheby *)x)->nbpasses = n;} -void pdp_imageproc_cheby_setcoef(void *x, u32 n, float f) -{ - - t_cheby *z = (t_cheby *)x; - if (n <= z->order){ - z->coefs[n] = (s32)(f * 32767.0f); // coefs are in s16.15 format - } - -} -void pdp_imageproc_cheby_process(void *x, u32 width, u32 height, s16 *image) -{ - - t_cheby *z = (t_cheby *)x; - u32 iterations = z->nbpasses; - u32 i,j,k; - s32 *c = z->coefs; - for (j=0; j < (height*width); j++){ - s32 acc = (s32)image[j]; - for (i=0; i<iterations; i++){ - s32 T2 = 0x7fff; /* 1 */ - s32 T1 = acc; - s32 t; - s32 in = acc; - acc = c[0] + ((in*c[1])>>15); - for (k=2; k<=z->order; k++){ - t = ((T1*in)>>14) - T2; /* T_n = 2 x T_n-1 - T_n-2 */ - T2 = T1; - T1 = t; - acc += ((c[k] * t)>>15); - } - } - image[j] = (s16)(CLAMP16(acc)); - } -} diff --git a/system/image/pdp_llconv.c b/system/image/pdp_llconv.c deleted file mode 100644 index 7fb17de..0000000 --- a/system/image/pdp_llconv.c +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Pure Data Packet system implementation. : low level format conversion code - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* this file contains low level image conversion code - nominated as "the ugliest part of pdp" - some code is mmx, most is not. */ - -#include "pdp_llconv.h" -#include "pdp_mmx.h" - - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - - -#define CLAMP8(x) (((x)<0) ? 0 : ((x>255)? 255 : (x))) -#define CLAMP16(x) (((x)<-0x7fff) ? -0x7fff : ((x>0x7fff) ? 0x7fff : (x))) -#define FP(x) ((int)(((float)(x)) * 256.0f)) - -#define CLAMP CLAMP8 - -/* some prototypes for functions defined elsewhere */ -void llconv_yvu_planar_s16u8(short int *src, unsigned char *dst, unsigned int nbpixels); -void llconv_yuv_planar_u8s16(unsigned char* source, short int *dest, int nbpixels); -void llconv_grey_s16u8(short int *src, unsigned char *dst, unsigned int nbpixels); -void llconv_yvu_planar_u8s16(unsigned char* source, short int *dest, int nbpixels); - - -static inline int rgb2y(int r, int g, int b){return (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16);} -static inline int rgb2v(int r, int g, int b){return (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b) + FP(128);} -static inline int rgb2u(int r, int g, int b){return -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b) + FP(128);} - - -/* swap top to bottom */ -static inline void _exchange_row(char *row1, char *row2, int size) -{ - int mask = ~(sizeof(int)-1); - int *irow1 = (int *)row1; - int *irow2 = (int *)row2; - - /* transfer words */ - while (size & mask){ - int tmp = *irow1; - *irow1++ = *irow2; - *irow2++ = tmp; - size -= sizeof(int); - } - - row1 = (char *)irow1; - row2 = (char *)irow2; - - /* transfer rest bytes */ - while (size){ - int tmp = *row1; - *row1++ = *row2; - *row2++ = tmp; - size--; - } -} - -void pdp_llconv_flip_top_bottom(char *data, int width, int height, int pixelsize) -{ - int linesize = width * pixelsize; - int i; - char *row1 = data; - char *row2 = data + linesize * (height-1); - - if (height <= 1) return; - if (width <= 0) return; - - while (row1 < row2){ - _exchange_row(row1, row2, linesize); - row1 += linesize; - row2 -= linesize; - } -} - -/* "standard" 8 bit conversion routine */ -static void llconv_rgb2yvu(unsigned char* src, unsigned char* dst, int nbpixels) -{ - int r,g,b,y,v,u,i; - for (i=0; i<nbpixels; i++){ - r = src[0]; - g = src[1]; - b = src[2]; - - y = rgb2y(r,g,b); - v = rgb2v(r,g,b); - u = rgb2u(r,g,b); - - dst[0] = CLAMP(y>>8); - dst[1] = CLAMP(v>>8); - dst[2] = CLAMP(u>>8); - - src += 3; - dst += 3; - } -} - -static void llconv_yvu16planar2rgbpacked(short int *src, unsigned char *dst, int w, int h) -{ - -/* -B = 1.164(Y - 16) + 2.018(U - 128) -G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) -R = 1.164(Y - 16) + 1.596(V - 128)} -*/ - - int r,g,b,y,u,v,b1,g1,r1,y1,xoff,yoff; - int size = w*h; - int voffset = size; - int uoffset = size + (size>>2); - int rgboff; - int rgbw = w*3; - int lumoff = 0; - int chromoff = 0; - - for(yoff=0; yoff<w*h; yoff+=2*w){ - for(xoff=0; xoff<w; xoff+=2){ - - /* calculate offsets */ - rgboff = 3 * (xoff + yoff); - lumoff = xoff + yoff; - chromoff = (xoff >> 1) + (yoff >> 2); - - /* get uv values */ - v = src[voffset + chromoff]; - u = src[uoffset + chromoff]; - - /* calculate chroma contrib for 2x2 pixblock */ - b1 = FP(2.018) * u; - g1 = FP(-0.813) * v + FP(-0.391) * u; - r1 = FP(1.596) * v; - - /* TOP LEFT */ - - /* top left luma contrib */ - y = src[lumoff] << 1; - y1 = FP(1.164) * y; - y1 -= FP(16*256); - - b = (b1 + y1)>>16; - g = (g1 + y1)>>16; - r = (r1 + y1)>>16; - - /* store top left rgb pixel */ - dst[rgboff+0] = CLAMP8(r); - dst[rgboff+1] = CLAMP8(g); - dst[rgboff+2] = CLAMP8(b); - - /* TOP RIGHT */ - - /* top right luma contrib */ - y = src[lumoff + 1] << 1; - y1 = FP(1.164) * y; - y1 -= FP(16*256); - - b = (b1 + y1)>>16; - g = (g1 + y1)>>16; - r = (r1 + y1)>>16; - - /* store top right rgb pixel */ - dst[rgboff+3] = CLAMP8(r); - dst[rgboff+4] = CLAMP8(g); - dst[rgboff+5] = CLAMP8(b); - - - /* BOTTOM LEFT */ - - /* bottom left luma contrib */ - y = src[lumoff+w] << 1; - y1 = FP(1.164) * y; - y1 -= FP(16*256); - - b = (b1 + y1)>>16; - g = (g1 + y1)>>16; - r = (r1 + y1)>>16; - - /* store bottom left rgb pixel */ - dst[rgboff+rgbw+0] = CLAMP8(r); - dst[rgboff+rgbw+1] = CLAMP8(g); - dst[rgboff+rgbw+2] = CLAMP8(b); - - /* BOTTOM RIGHT */ - - /* bottom right luma contrib */ - y = src[lumoff + w + 1] << 1; - y1 = FP(1.164) * y; - y1 -= FP(16*256); - - b = (b1 + y1)>>16; - g = (g1 + y1)>>16; - r = (r1 + y1)>>16; - - /* store bottom right rgb pixel */ - dst[rgboff+rgbw+3] = CLAMP8(r); - dst[rgboff+rgbw+4] = CLAMP8(g); - dst[rgboff+rgbw+5] = CLAMP8(b); - - } - - } - -} - - - -/* 8 bit rgb to 16 bit planar subsampled yvu */ -static void llconv_rgb2yvu_planar16sub(unsigned char* src, short int* dst, int w, int h) -{ - int r,g,b,y,v,u,i,j,k; - int size = w*h; - - int voffset = size; - int uoffset = size + (size>>2); - - - int loffset = w * 3; - - k=0; - for (j=0; j<w*h; j+=(w<<1)){ - k = 3 * j; - for (i=0; i<w; i+=2){ - - - // well, this seems to work... strange though - r = src[k]; - g = src[k+1]; - b = src[k+2]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v = (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u = -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[i+j] = CLAMP16(y >> 1); - - r = src[k+3]; - g = src[k+4]; - b = src[k+5]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v += (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u += -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[i+j+1] = CLAMP16(y >> 1); - - - - r = src[loffset + k]; - g = src[loffset + k+1]; - b = src[loffset + k+2]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v = (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u = -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[w+i+j] = CLAMP16(y >> 1); - - r = src[loffset + k+3]; - g = src[loffset + k+4]; - b = src[loffset + k+5]; - - k += 6; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v += (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u += -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[w+i+j+1] = CLAMP16(y >> 1); - - dst[uoffset+ (i>>1) + (j>>2)] = (CLAMP16(u >> 1)); - dst[voffset+ (i>>1) + (j>>2)] = (CLAMP16(v >> 1)); - } - } -} - - -/* 8 bit rgb to 8 bit planar subsampled yvu */ -static void llconv_rgb2yvu_planar8sub(unsigned char* src, unsigned char *dst, int w, int h) -{ - int r,g,b,y,v,u,i,j,k; - int size = w*h; - - int voffset = size; - int uoffset = size + (size>>2); - - - int loffset = w * 3; - - k=0; - for (j=0; j<w*h; j+=(w<<1)){ - k = 3 * j; - for (i=0; i<w; i+=2){ - - - // well, this seems to work... strange though - r = src[k]; - g = src[k+1]; - b = src[k+2]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v = (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u = -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[i+j] = CLAMP8(y >> 8); - - r = src[k+3]; - g = src[k+4]; - b = src[k+5]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v += (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u += -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[i+j+1] = CLAMP8(y >> 8); - - - - r = src[loffset + k]; - g = src[loffset + k+1]; - b = src[loffset + k+2]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v = (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u = -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[w+i+j] = CLAMP8(y >> 8); - - r = src[loffset + k+3]; - g = src[loffset + k+4]; - b = src[loffset + k+5]; - - k += 6; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v += (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u += -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[w+i+j+1] = CLAMP8(y >> 8); - - dst[uoffset+ (i>>1) + (j>>2)] = (CLAMP8((u >> 9)+128)); - dst[voffset+ (i>>1) + (j>>2)] = (CLAMP8((v >> 9)+128)); - } - } -} - - -/* 8 bit bgr to 16 bit planar subsampled yvu */ -static void llconv_bgr2yvu_planar16sub(unsigned char* src, short int* dst, int w, int h) -{ - int r,g,b,y,v,u,i,j,k; - int size = w*h; - - int voffset = size; - int uoffset = size + (size>>2); - - - int loffset = w * 3; - - k=0; - for (j=0; j<w*h; j+=(w<<1)){ - k = 3 * j; - for (i=0; i<w; i+=2){ - - - // well, this seems to work... strange though - b = src[k]; - g = src[k+1]; - r = src[k+2]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v = (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u = -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[i+j] = CLAMP16(y >> 1); - - b = src[k+3]; - g = src[k+4]; - r = src[k+5]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v += (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u += -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[i+j+1] = CLAMP16(y >> 1); - - - - b = src[loffset + k]; - g = src[loffset + k+1]; - r = src[loffset + k+2]; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v = (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u = -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[w+i+j] = CLAMP16(y >> 1); - - b = src[loffset + k+3]; - g = src[loffset + k+4]; - r = src[loffset + k+5]; - - k += 6; - - y = (FP(0.257) * r) + (FP(0.504) * g) + (FP(0.098) * b) + FP(16); - v += (FP(0.439) * r) - (FP(0.368) * g) - (FP(0.071) * b); - u += -(FP(0.148) * r) - (FP(0.291) * g) + (FP(0.439) * b); - - dst[w+i+j+1] = CLAMP16(y >> 1); - - dst[uoffset+ (i>>1) + (j>>2)] = (CLAMP16(u >> 1)); - dst[voffset+ (i>>1) + (j>>2)] = (CLAMP16(v >> 1)); - } - } -} - -/* these seem to be pretty slow */ - -static void llconv_yvu2rgb(unsigned char* src, unsigned char* dst, int nbpixels) -{ - int r,g,b,y,v,u,i; - for (i=0; i<nbpixels; i++){ - y = src[0]; - v = src[1]; - u = src[2]; - - - b = FP(1.164) * (y - 16) + FP(2.018) * (u - 128); - g = FP(1.164) * (y - 16) - FP(0.813) * (v - 128) - FP(0.391) * (u - 128); - r = FP(1.164) * (y - 16) + FP(1.596) * (v - 128); - - dst[0] = CLAMP(r>>8); - dst[1] = CLAMP(g>>8); - dst[2] = CLAMP(b>>8); - - src += 3; - dst += 3; - } -} - - - -/* convert yvu to yuyv */ -static void llconv_yvu2yuyv(unsigned char *src, unsigned char *dst, unsigned int nbpixels) -{ - unsigned int y1, y2, u, v, i; - - for (i = 0; i < nbpixels/2; i++){ - - y1 = src[0]; - y2 = src[3]; - v = (src[1] + src[4]) >> 1; - u = (src[2] + src[5]) >> 1; - dst[0] = y1; - dst[1] = u; - dst[2] = y2; - dst[3] = v; - - src += 6; - dst += 4; - - } - -} - - - -/* convert yuvu packed 8 bit unsigned to yv12 planar 16bit signed */ -static void llconv_yuyv_packed_u8s16(unsigned char* ucsource, short int *sidest, unsigned int w, unsigned int h) -{ - unsigned int i, j; - unsigned int *source = (unsigned int *)ucsource; - - unsigned int *dest = (unsigned int *)sidest; - unsigned int uoffset = (w*h)>>1; - unsigned int voffset = (w*h + ((w*h) >> 2)) >> 1; - - for(j=0; j < (h*w)>>1; j +=(w)){ - for(i=0; i< (w>>1); i+=2){ - unsigned int y,u,v; - unsigned int v00, v01, v10, v11; - v00 = source[i+j]; - v01 = source[i+j+1]; - v10 = source[i+j+(w>>1)]; - v11 = source[i+j+(w>>1)+1]; - - // save luma - dest[i+j] = ((v00 & 0x00ff00ff) << 7); - dest[i+j+1] = ((v01 & 0x00ff00ff) << 7); - dest[i+j+(w>>1)] = ((v10 & 0x00ff00ff) << 7); - dest[i+j+(w>>1)+1] = ((v11 & 0x00ff00ff) << 7); - - // compute chroma - - // mask out luma & shift right - v00 = (v00 & 0xff00ff00)>>1; - v01 = (v01 & 0xff00ff00)>>1; - v10 = (v10 & 0xff00ff00)>>1; - v11 = (v11 & 0xff00ff00)>>1; - - // average 2 scan lines - v00 += v10; - v01 += v11; - - // combine - v = (v01 << 16) | (v00 & 0x0000ffff); - u = (v01 & 0xffff0000) | (v00 >> 16); - - // flip sign bits for u,v - u ^= 0x80008000; - v ^= 0x80008000; - - // save chroma - dest[uoffset + (i>>1) + (j>>2)] = u; - dest[voffset + (i>>1) + (j>>2)] = v; - } - } - - -} - -#define CONVERT(x,y) ((x) + ((y)<<16)) - -void pdp_llconv(void *src, int stype, void *dst, int dtype, int w, int h) -{ - int conversion = CONVERT(stype, dtype); - void *tmpbuf; - - switch(CONVERT(stype, dtype)){ - - case CONVERT( RIF_YVU__P411_U8, RIF_YVU__P411_S16 ): - llconv_yvu_planar_u8s16((unsigned char*)src, (short int *)dst, w*h); - break; - - case CONVERT( RIF_YUV__P411_U8, RIF_YVU__P411_S16 ): - llconv_yuv_planar_u8s16((unsigned char*)src, (short int *)dst, w*h); - break; - - case CONVERT( RIF_YUYV_P____U8, RIF_YVU__P411_S16 ): - llconv_yuyv_packed_u8s16((unsigned char*)src, (short int *)dst, w, h); - break; - - case CONVERT( RIF_RGB__P____U8, RIF_YVU__P411_U8 ): - llconv_rgb2yvu_planar8sub((unsigned char*) src, (unsigned char*) dst, w, h); - break; - - case CONVERT( RIF_RGB__P____U8, RIF_YVU__P411_S16 ): - llconv_rgb2yvu_planar16sub((unsigned char*) src, (short int*) dst, w, h); - break; - - case CONVERT( RIF_BGR__P____U8, RIF_YVU__P411_S16 ): - llconv_bgr2yvu_planar16sub((unsigned char*) src, (short int*) dst, w, h); - break; - - case CONVERT( RIF_YVU__P411_S16, RIF_RGB__P____U8 ): - llconv_yvu16planar2rgbpacked((short int*) src, (unsigned char*) dst, w, h); - break; - - case CONVERT( RIF_YVU__P411_S16, RIF_YVU__P411_U8 ): - llconv_yvu_planar_s16u8((short int*)src, (unsigned char*)dst, w*h); - break; - - case CONVERT( RIF_GREY______S16, RIF_GREY______U8 ): - llconv_grey_s16u8((short int*)src, (unsigned char*)dst, w*h); - break; - default: - post("pdp_llconv: WARNING: no conversion routine defined for (%d)->(%d)", stype, dtype); - - } - -} - - -#ifdef __cplusplus -} -#endif diff --git a/system/image/pdp_llconv_mmx.c b/system/image/pdp_llconv_mmx.c deleted file mode 100644 index 8070bac..0000000 --- a/system/image/pdp_llconv_mmx.c +++ /dev/null @@ -1,55 +0,0 @@ - -/* - * Pure Data Packet system implementation. : wrapper for mmx low level format conversion code - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include "pdp_mmx.h" - - - -/* convert greyscale 8 bit unsigned to 16bit signed */ -void llconv_grey_s16u8(short int *src, unsigned char *dst, unsigned int nbpixels) -{ - pixel_pack_s16u8_y(src, dst, nbpixels>>3); -} - -/* convert yvu planar 411 16 bit signed to 8 bit unsigned */ -void llconv_yvu_planar_s16u8(short int *src, unsigned char *dst, unsigned int nbpixels) -{ - pixel_pack_s16u8_y(src, dst, nbpixels>>3); - pixel_pack_s16u8_uv(src + nbpixels, dst + nbpixels, nbpixels>>4); -} - - -/* convert yvu planar 411 8 bit unsigned to yv12 planar 16bit signed */ -void llconv_yvu_planar_u8s16(unsigned char* source, short int *dest, int nbpixels) -{ - pixel_unpack_u8s16_y(source, dest, nbpixels>>3); - pixel_unpack_u8s16_uv(&source[nbpixels], &dest[nbpixels], nbpixels>>4); -} - -/* convert yuv planar 411 8 bit unsigned to yv12 planar 16bit signed */ -void llconv_yuv_planar_u8s16(unsigned char* source, short int *dest, int nbpixels) -{ - pixel_unpack_u8s16_y(source, dest, nbpixels>>3); - pixel_unpack_u8s16_uv(&source[nbpixels], &dest[nbpixels + (nbpixels>>2)], nbpixels>>5); - pixel_unpack_u8s16_uv(&source[nbpixels + (nbpixels>>2)], &dest[nbpixels], nbpixels>>5); -} - diff --git a/system/image/pdp_llconv_portable.c b/system/image/pdp_llconv_portable.c deleted file mode 100644 index f6d5a44..0000000 --- a/system/image/pdp_llconv_portable.c +++ /dev/null @@ -1,82 +0,0 @@ - -/* - * Pure Data Packet system implementation. : portable low level format conversion code - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#define CLAMP(x) (((x)<0) ? 0 : ((x>255)? 255 : (x))) -#define FP(x) ((int)(((float)(x)) * 256.0f)) - -void pixel_unpack_portable_u8s16_y(unsigned char *src ,short int *dst, unsigned int nbpixels) -{ - unsigned int i; - for (i=0; i<nbpixels; i++) dst[i] = ((short int)(src[i])) << 7; -} - -void pixel_unpack_portable_u8s16_uv(unsigned char *src ,short int *dst, unsigned int nbpixels) -{ - unsigned int i; - for (i=0; i<nbpixels; i++) dst[i] = (((short int)(src[i])) << 8) ^ 0x8000; -} - - -void pixel_pack_portable_s16u8_y(short int *src, unsigned char *dst, unsigned int nbpixels) -{ - unsigned int i; - for (i=0; i<nbpixels; i++) dst[i] = (unsigned char)(CLAMP(src[i]>>7)); -} - -void pixel_pack_portable_s16u8_uv(short int *src, unsigned char *dst, unsigned int nbpixels) -{ - unsigned int i; - unsigned short *usrc = (unsigned short *)src; - for (i=0; i<nbpixels; i++) dst[i] = ((usrc[i]^0x8000)>>8); -} - - -/* convert greyscale 8 bit unsigned to 16bit signed */ -void llconv_grey_s16u8(short int *src, unsigned char *dst, unsigned int nbpixels) -{ - pixel_pack_portable_s16u8_y(src, dst, nbpixels); -} - -/* convert yvu planar 411 16 bit signed to 8 bit unsigned */ -void llconv_yvu_planar_s16u8(short int *src, unsigned char *dst, unsigned int nbpixels) -{ - pixel_pack_portable_s16u8_y(src, dst, nbpixels); - pixel_pack_portable_s16u8_uv(src + nbpixels, dst + nbpixels, nbpixels>>1); - -} - - -/* convert yvu planar 411 8 bit unsigned to yv12 planar 16bit signed */ -void llconv_yvu_planar_u8s16(unsigned char* source, short int *dest, int nbpixels) -{ - pixel_unpack_portable_u8s16_y(source, dest, nbpixels); - pixel_unpack_portable_u8s16_uv(&source[nbpixels], &dest[nbpixels], nbpixels>>1); -} - -/* convert yuv planar 411 8 bit unsigned to yv12 planar 16bit signed */ -void llconv_yuv_planar_u8s16(unsigned char* source, short int *dest, int nbpixels) -{ - pixel_unpack_portable_u8s16_y(source, dest, nbpixels); - pixel_unpack_portable_u8s16_uv(&source[nbpixels], &dest[nbpixels + (nbpixels>>2)], nbpixels>>2); - pixel_unpack_portable_u8s16_uv(&source[nbpixels + (nbpixels>>2)], &dest[nbpixels], nbpixels>>2); -} - - diff --git a/system/image/pdp_resample.c b/system/image/pdp_resample.c deleted file mode 100644 index d2ffbcd..0000000 --- a/system/image/pdp_resample.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Pure Data Packet system file. - image resampling routines - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include "pdp_resample.h" -#include "pdp.h" -#include <string.h> - -/* - -efficient bilinear resampling ?? -performance: how to eliminate divides? -> virtual coordinates 2^k x 2^k (conf. opengl) - -i.e. 16 bit virtual coordinates: easy modular addressing - -*/ - - -/* code in this file should go out to be replaced by code in pdp_imageproc */ - -static s32 pdp_resample_bilin(s16 *image, s32 width, s32 height, s32 virt_x, s32 virt_y) -{ - - s32 fp_x, fp_y, frac_x, frac_y, f, offset, r_1, r_2; - - virt_x &= 0xffff; - virt_y &= 0xffff; - - fp_x = virt_x * (width - 1); - fp_y = virt_y * (height - 1); - - frac_x = fp_x & (0xffff); - frac_y = fp_y & (0xffff); - - offset = (fp_x >> 16) + (fp_y >> 16) * width; - image += offset; - - f = 0x10000 - frac_x; - - r_1 = ((f * (s32)(image[0]) + frac_x * (s32)(image[1])))>>16; - - image += width; - - r_2 = ((f * (s32)(image[0]) + frac_x * (s32)(image[1])))>>16; - - f = 0x10000 - frac_y; - - return ((f * r_1 + frac_y * r_2)>>16); - -} - - -void pdp_resample_scale_bilin(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h, s32 dst_w, s32 dst_h) -{ - s32 i,j; - s32 virt_x=0; - s32 virt_y=0; /* virtual coordinates in 30 bit */ - s32 scale_x = 0x40000000 / dst_w; - s32 scale_y = 0x40000000 / dst_h; - - for (j=0; j<dst_h; j++){ - for (i=0; i<dst_w; i++){ - *dst_image++ = pdp_resample_bilin(src_image, src_w, src_h, virt_x>>14, virt_y>>14); - virt_x += scale_x; - } - virt_x = 0; - virt_y += scale_y; - } - -} - -void pdp_resample_scale_nn(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h, s32 dst_w, s32 dst_h) -{ - s32 i,j; - s32 x=0; - s32 y=0; - s32 frac_x=0; - s32 frac_y=0; - s32 scale_x = (src_w << 20 ) / dst_w; - s32 scale_y = (src_h << 20 ) / dst_h; - - for (j=0; j<dst_h; j++){ - for (i=0; i<dst_w; i++){ - *dst_image++ = src_image[x+y]; - frac_x += scale_x; - x = frac_x >> 20; - } - x = 0; - frac_x = 0; - frac_y += scale_y; - y = (frac_y >> 20) * src_w; - } - -} - -/* USE pdp_resample_affinemap -void pdp_resample_zoom_tiled_bilin(s16 *src_image, s16 *dst_image, s32 w, s32 h, - float zoom_x, float zoom_y, float center_x_relative, float center_y_relative) -{ - float izx = 1.0f / zoom_x; - float izy = 1.0f / zoom_y; - s32 scale_x = (s32)((float)0x100000 * izx / (float)w); - s32 scale_y = (s32)((float)0x100000 * izy / (float)h); - - s32 top_virt_x = (s32)((1.0f - izx) * (float)0x100000 * center_x_relative); - s32 top_virt_y = (s32)((1.0f - izy) * (float)0x100000 * center_y_relative); - - s32 virt_x = top_virt_x; - s32 virt_y = top_virt_y; - - s32 i,j; - - for (j=0; j<h; j++){ - for (i=0; i<w; i++){ - *dst_image++ = pdp_resample_bilin(src_image, w, h, virt_x>>4, virt_y>>4); - virt_x += scale_x; - } - virt_x = top_virt_x; - virt_y += scale_y; - } - -} -*/ - -void pdp_resample_halve(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h) -{ - - int dst_x,dst_y; - int src_x = 0; - int src_y = 0; - int dst_w = src_w >> 1; - int dst_h = src_h >> 1; - s32 tmp1,tmp2,tmp3,tmp4; - - //post("%x %x %d %d\n", src_image, dst_image, src_w, src_h); - - for(dst_y = 0; dst_y < dst_h * dst_w; dst_y += dst_w){ - for (dst_x = 0; dst_x < dst_w; dst_x++){ - - tmp1 = (s32)src_image[src_y + src_x]; - tmp2 = (s32)src_image[src_y + src_x + 1]; - tmp3 = (s32)src_image[src_y + src_x + src_w]; - tmp4 = (s32)src_image[src_y + src_x + src_w + 1]; - - tmp1 += tmp2; - tmp3 += tmp4; - - src_x += 2; - - dst_image[dst_x+dst_y] = (s16)((tmp1 + tmp3)>>2); - } - src_y += src_w << 1; - src_x = 0; - } -} - -void pdp_resample_double(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h) -{ - int src_x = 0; - int src_y = 0; - int dst = 0; - int dst_w = src_w << 1; - - s16 tmp; - - for(src_y = 0; src_y < src_h * src_w; src_y += src_w){ - for (src_x = 0; src_x < src_w; src_x++){ - - tmp = *src_image++; - dst = (src_y << 2) + (src_x << 1); - dst_image[dst] = tmp; - dst_image[dst+1] = tmp; - dst+=dst_w; - dst_image[dst] = tmp; - dst_image[dst+1] = tmp; - } - } -} - -/* $$$TODO: finish this */ -void pdp_resample_padcrop(s16 *src_image, s16 *dst_image, s32 src_w, s32 src_h, s32 dst_w, s32 dst_h) -{ - - int shift_x = (dst_w - src_w) / 2; - int shift_y = (dst_h - src_h) / 2; -} - diff --git a/system/kernel/CONTENTS b/system/kernel/CONTENTS deleted file mode 100644 index c2f7c8c..0000000 --- a/system/kernel/CONTENTS +++ /dev/null @@ -1,7 +0,0 @@ -debug debug stuff -forth the forth system -list the list implementation -mem memory allocation stuf -packet the packet memory manager -type the type handling and conversion system -symbol symbol implementation, with namespaces for forth, types, classes, ... diff --git a/system/kernel/Makefile b/system/kernel/Makefile deleted file mode 100644 index f1d82a9..0000000 --- a/system/kernel/Makefile +++ /dev/null @@ -1,16 +0,0 @@ - -OBJECTS = pdp.o pdp_ut.o pdp_packet.o pdp_queue.o pdp_comm.o \ - pdp_control.o pdp_compat.o pdp_type.o pdp_dpd_command.o \ - pdp_list.o pdp_forth.o - - -include ../../Makefile.config - -all: pdp_main_clean $(OBJECTS) - -pdp_main_clean: - rm -f pdp.o - -clean: - rm -f *~ - rm -f *.o diff --git a/system/kernel/pdp.c b/system/kernel/pdp.c deleted file mode 100644 index d71e655..0000000 --- a/system/kernel/pdp.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Pure Data Packet system implementation: setup code - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "pdp_config.h" -#include "pdp.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - -/* module setup declarations (all C-style) */ - -/* pdp system / internal stuff */ -void pdp_list_setup(void); -void pdp_sym_setup(void); -void pdp_forth_setup(void); -void pdp_type_setup(void); -void pdp_packet_setup(void); -void pdp_ut_setup(void); -void pdp_queue_setup(void); -void pdp_control_setup(void); -void pdp_image_setup(void); -void pdp_bitmap_setup(void); -void pdp_matrix_setup(void); - - -/* pdp modules */ -void pdp_xv_setup(void); -void pdp_add_setup(void); -void pdp_mul_setup(void); -void pdp_mix_setup(void); -void pdp_randmix_setup(void); -void pdp_qt_setup(void); -void pdp_v4l_setup(void); -void pdp_reg_setup(void); -void pdp_conv_setup(void); -void pdp_bq_setup(void); -void pdp_del_setup(void); -void pdp_snap_setup(void); -void pdp_trigger_setup(void); -void pdp_route_setup(void); -void pdp_noise_setup(void); -void pdp_gain_setup(void); -void pdp_chrot_setup(void); -void pdp_scope_setup(void); -void pdp_scale_setup(void); -void pdp_zoom_setup(void); -void pdp_scan_setup(void); -void pdp_scanxy_setup(void); -void pdp_sdl_setup(void); -void pdp_cheby_setup(void); -void pdp_grey2mask_setup(void); -void pdp_constant_setup(void); -void pdp_logic_setup(void); -void pdp_glx_setup(void); -void pdp_loop_setup(void); -void pdp_description_setup(void); -void pdp_convert_setup(void); -void pdp_stateless_setup(void); -void pdp_mat_mul_setup(void); -void pdp_mat_lu_setup(void); -void pdp_mat_vec_setup(void); -void pdp_plasma_setup(void); -void pdp_cog_setup(void); -void pdp_histo_setup(void); -void pdp_array_setup(void); - -/* hacks */ -void pdp_inspect_setup(void); -void pdp_slice_cut_setup(void); -void pdp_slice_glue_setup(void); - -/* testing */ -void pdp_dpd_test_setup(void); -void pdp_forthproc_setup(void); - - - -/* library setup routine */ -void pdp_setup(void){ - - /* babble */ - post ("PDP: pure data packet"); - -#ifdef PDP_VERSION - fprintf(stderr, "PDP: version " PDP_VERSION "\n"); -#endif - - - /* setup pdp system */ - pdp_list_setup(); - pdp_type_setup(); - pdp_sym_setup(); - pdp_packet_setup(); - pdp_forth_setup(); - pdp_control_setup(); - - pdp_image_setup(); - pdp_bitmap_setup(); - pdp_matrix_setup(); - - pdp_queue_setup(); - - /* setup utility toolkit */ - pdp_ut_setup(); - - /* setup pdp modules*/ - pdp_add_setup(); - pdp_mul_setup(); - pdp_mix_setup(); - pdp_randmix_setup(); - pdp_reg_setup(); - pdp_conv_setup(); - pdp_bq_setup(); - pdp_del_setup(); - pdp_snap_setup(); - pdp_trigger_setup(); - pdp_route_setup(); - pdp_noise_setup(); - pdp_plasma_setup(); - pdp_gain_setup(); - pdp_chrot_setup(); - pdp_scope_setup(); - pdp_scale_setup(); - pdp_zoom_setup(); - pdp_scan_setup(); - pdp_scanxy_setup(); - pdp_cheby_setup(); - pdp_grey2mask_setup(); - pdp_constant_setup(); - pdp_logic_setup(); - pdp_loop_setup(); - pdp_description_setup(); - pdp_convert_setup(); - pdp_stateless_setup(); - pdp_mat_mul_setup(); - pdp_mat_lu_setup(); - pdp_mat_vec_setup(); - pdp_cog_setup(); - pdp_histo_setup(); - pdp_array_setup(); - - /* experimental stuff */ - pdp_slice_cut_setup(); - pdp_slice_glue_setup(); - pdp_inspect_setup(); - - /* testing */ - //pdp_dpd_test_setup(); - pdp_forthproc_setup(); - - /* optional modules */ - -#ifdef HAVE_PDP_QT - pdp_qt_setup(); -#endif - -#ifdef HAVE_PDP_XV - pdp_xv_setup(); -#endif - -#ifdef HAVE_PDP_SDL - pdp_sdl_setup(); -#endif - -#ifdef HAVE_PDP_V4L - pdp_v4l_setup(); -#endif - -#ifdef HAVE_PDP_GLX - pdp_glx_setup(); -#endif - -} - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_comm.c b/system/kernel/pdp_comm.c deleted file mode 100644 index bcc0e3a..0000000 --- a/system/kernel/pdp_comm.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Pure Data Packet system implementation. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* this file contains misc communication (packet) methods for pd */ - - -#include "pdp.h" -#include "pdp_internals.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - -t_symbol *_pdp_sym_pdp; -t_symbol *_pdp_sym_rro; -t_symbol *_pdp_sym_rrw; -t_symbol *_pdp_sym_prc; -t_symbol *_pdp_sym_dpd; -t_symbol *_pdp_sym_ins; -t_symbol *_pdp_sym_acc; - -t_symbol *pdp_sym_pdp() {return _pdp_sym_pdp;} -t_symbol *pdp_sym_rro() {return _pdp_sym_rro;} -t_symbol *pdp_sym_rrw() {return _pdp_sym_rrw;} -t_symbol *pdp_sym_prc() {return _pdp_sym_prc;} -t_symbol *pdp_sym_dpd() {return _pdp_sym_dpd;} -t_symbol *pdp_sym_ins() {return _pdp_sym_ins;} -t_symbol *pdp_sym_acc() {return _pdp_sym_acc;} - -/************** packet management and communication convenience functions ************/ - -/* send a packet to an outlet */ -void outlet_pdp(t_outlet *out, int packetid) -{ - t_atom atom[2]; - - SETFLOAT(atom+1, (float)packetid); - - SETSYMBOL(atom+0, pdp_sym_rro()); - outlet_anything(out, pdp_sym_pdp(), 2, atom); - - SETSYMBOL(atom+0, pdp_sym_rrw()); - outlet_anything(out, pdp_sym_pdp(), 2, atom); - - SETSYMBOL(atom+0, pdp_sym_prc()); - outlet_anything(out, pdp_sym_pdp(), 2, atom); - -} - -/* send an accumulation packet to an outlet */ -void outlet_dpd(t_outlet *out, int packetid) -{ - t_atom atom[2]; - - SETFLOAT(atom+1, (float)packetid); - - SETSYMBOL(atom+0, pdp_sym_ins()); - outlet_anything(out, pdp_sym_dpd(), 2, atom); - - SETSYMBOL(atom+0, pdp_sym_acc()); - outlet_anything(out, pdp_sym_dpd(), 2, atom); - -} - -/* unregister a packet and send it to an outlet */ -void - -pdp_packet_pass_if_valid(t_outlet *outlet, int *packet_ptr) -{ - t_pdp *header = pdp_packet_header(*packet_ptr); - //if (-1 != *packet){ - if (header){ - /* if packet is exclusively owned, mark as passing */ - if (1 == header->users) pdp_packet_mark_passing(packet_ptr); - - /* send */ - outlet_pdp(outlet, *packet_ptr); - - /* if the packet is still here (was passing and not registered, - or it was a shared copy): unregister it */ - if (-1 != *packet_ptr){ - pdp_packet_unmark_passing(*packet_ptr); - pdp_packet_mark_unused(*packet_ptr); - *packet_ptr = -1; - } - } -} - -void -pdp_packet_replace_if_valid(int *dpacket, int *spacket) -{ - if (-1 != *spacket){ - pdp_packet_mark_unused(*dpacket); - *dpacket = *spacket; - *spacket = -1; - } - -} - - -int -pdp_packet_copy_ro_or_drop(int *dpacket, int spacket) -{ - int drop = 0; - if (*dpacket == -1) *dpacket = pdp_packet_copy_ro(spacket); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - - -int -pdp_packet_copy_rw_or_drop(int *dpacket, int spacket) -{ - int drop = 0; - if (*dpacket == -1) *dpacket = pdp_packet_copy_rw(spacket); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - -int -pdp_packet_convert_ro_or_drop(int *dpacket, int spacket, t_pdp_symbol *template) -{ - int drop = 0; - - if (!template) return pdp_packet_copy_ro_or_drop(dpacket, spacket); - - if (*dpacket == -1) *dpacket = pdp_packet_convert_ro(spacket, template); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - - -int -pdp_packet_convert_rw_or_drop(int *dpacket, int spacket, t_pdp_symbol *template) -{ - int drop = 0; - - if (!template) return pdp_packet_copy_rw_or_drop(dpacket, spacket); - - if (*dpacket == -1) *dpacket = pdp_packet_convert_rw(spacket, template); - else { - /* send a notification there is a dropped packet */ - pdp_control_notify_drop(spacket); - drop = 1; - } - return drop; -} - - -void -pdp_sym_setup(void) -{ - _pdp_sym_pdp = gensym("pdp"); - _pdp_sym_rro = gensym("register_ro"); - _pdp_sym_rrw = gensym("register_rw"); - _pdp_sym_prc = gensym("process"); - _pdp_sym_dpd = gensym("dpd"); - _pdp_sym_ins = gensym("inspect"); - _pdp_sym_acc = gensym("accumulate"); -} - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_compat.c b/system/kernel/pdp_compat.c deleted file mode 100644 index 4bcf00d..0000000 --- a/system/kernel/pdp_compat.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Pure Data Packet system implementation. Compatibility routines. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* this file contains misc communication methods */ - - -#include "pdp.h" -#include "pdp_internals.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - - - -void -pdp_pass_if_valid(t_outlet *outlet, int *packet) -{ - pdp_packet_pass_if_valid(outlet, packet); -} - -void -pdp_replace_if_valid(int *dpacket, int *spacket) -{ - pdp_packet_replace_if_valid(dpacket, spacket); - -} - - - - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_control.c b/system/kernel/pdp_control.c deleted file mode 100644 index 2cba7b7..0000000 --- a/system/kernel/pdp_control.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Pure Data Packet system implementation: control object - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* this is an actual pd class that is used for communication with the - pdp framework */ - -#include "pdp.h" -#include "pdp_internals.h" -#include "pdp_control.h" -#include <stdio.h> - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - - - -static long dropped_packets; - -static t_class* pdp_control_class; - - -/* pdp control instance data */ - -struct _pdp_control; -typedef struct _pdp_control -{ - t_object x_obj; - t_outlet *x_outlet0; - struct _pdp_control *x_next; - -} t_pdp_control; - - - -static t_pdp_control *pdp_control_list; - -static void pdp_control_info(t_pdp_control *x) -{ -} - -static void pdp_control_collectgarbage(t_pdp_control *x) -{ - int nb_packets_freed = pdp_pool_collect_garbage(); - post("pdp_control: freed %d packets", nb_packets_freed); - -} - -static void pdp_control_set_mem_limit(t_pdp_control *x, t_floatarg f) -{ - int limit = (int)f; - if (limit < 0) limit = 0; - pdp_pool_set_max_mem_usage(limit); - if (limit) post("pdp_control: set memory limit to %d bytes", limit); - else post("pdp_control: disabled memory limit"); - -} - -static void pdp_control_thread(t_pdp_control *x, t_floatarg f) -{ - int t = (int)f; - - if (t){ - post("pdp_control: pdp is now using its own processing thread"); - pdp_queue_use_thread(1); - } - else { - post("pdp_control: pdp is now using the main pd thread"); - pdp_queue_use_thread(0); - } -} - - -static void pdp_control_send_drop_message(t_pdp_control *x) -{ - t_atom atom[1]; - t_symbol *s = gensym("pdp_drop"); - - SETFLOAT(atom+0, (float)dropped_packets); - outlet_anything(x->x_outlet0, s, 1, atom); -} - - -static void pdp_control_free(t_pdp_control *x) -{ - /* remove from linked list */ - t_pdp_control *curr = pdp_control_list; - if (pdp_control_list == x) pdp_control_list = x->x_next; - else while (curr){ - if (curr->x_next == x) { - curr->x_next = x->x_next; - break; - } - else { - curr = curr->x_next; - } - - } -} - - -static void *pdp_control_new(void) -{ - t_pdp_control *x = (t_pdp_control *)pd_new(pdp_control_class); - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); - - /* add to list */ - x->x_next = pdp_control_list; - pdp_control_list = x; - return x; -} - -/************************* class methods ***************************************/ - - -void pdp_control_addmethod(t_method m, t_symbol *s) -{ - class_addmethod(pdp_control_class, m, s, A_GIMME, A_NULL); -} - -void pdp_control_setup(void) -{ - - pdp_control_list = 0; - dropped_packets = 0; - - /* setup pd class data */ - pdp_control_class = class_new(gensym("pdp_control"), (t_newmethod)pdp_control_new, - (t_method)pdp_control_free, sizeof(t_pdp_control), 0, A_NULL); - - - class_addmethod(pdp_control_class, (t_method)pdp_control_info, gensym("info"), A_NULL); - class_addmethod(pdp_control_class, (t_method)pdp_control_thread, gensym("thread"), A_DEFFLOAT, A_NULL); - class_addmethod(pdp_control_class, (t_method)pdp_control_collectgarbage, gensym("collectgarbage"), A_NULL); - class_addmethod(pdp_control_class, (t_method)pdp_control_set_mem_limit, gensym("memlimit"), A_FLOAT, A_NULL); -} - - - -void pdp_control_notify_broadcast(t_pdp_control_method_notify *notify) -{ - t_pdp_control *curr = pdp_control_list; - while (curr){ - (*notify)(curr); - curr = curr->x_next; - } -} - - - -/************************* notify class methods *************************/ - -void pdp_control_notify_drop(int packet) -{ - dropped_packets++; - - /* send drop notify to controller class instances */ - pdp_control_notify_broadcast(pdp_control_send_drop_message); - //post("dropped packet"); -} - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_debug.c b/system/kernel/pdp_debug.c deleted file mode 100644 index 07f6541..0000000 --- a/system/kernel/pdp_debug.c +++ /dev/null @@ -1,21 +0,0 @@ -#include <sys/types.h> -#include <signal.h> -#include <unistd.h> -#include "pdp_post.h" - -int pdp_debug_sigtrap_on_assert; - - -void pdp_assert_hook (char *condition, char *file, int line) -{ - pdp_post("PDP_ASSERT (%s) failed in file %s, line %u. ", condition, file, line); - pdp_post("%s.\n", pdp_debug_sigtrap_on_assert ? "sending SIGTRAP" : "continuing"); - - if (pdp_debug_sigtrap_on_assert) kill(getpid(), SIGTRAP); -} - - -void pdp_debug_setup(void) -{ - pdp_debug_sigtrap_on_assert = 1; -} diff --git a/system/kernel/pdp_dpd_command.c b/system/kernel/pdp_dpd_command.c deleted file mode 100644 index 0d3ecf1..0000000 --- a/system/kernel/pdp_dpd_command.c +++ /dev/null @@ -1,87 +0,0 @@ - -/* - * Pure Data Packet header file. DPD command class - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* this object implements a dpd command queue and command object */ - -#include "pdp.h" -#include "pdp_dpd_command.h" - -void pdp_dpd_commandfactory_init(t_pdp_dpd_commandfactory *x, u32 size) -{ - x->nb_commands = 0; - x->command_size = size; - x->command = 0; -} - -void _pdp_dpd_commandfactory_free(t_pdp_dpd_command *x) -{ - if (x) _pdp_dpd_commandfactory_free(x->next); - pdp_dealloc(x); -} - -void pdp_dpd_commandfactory_free(t_pdp_dpd_commandfactory *x) -{ - _pdp_dpd_commandfactory_free(x->command); - x->command = 0; - x->nb_commands = 0; -} - - -/* factory method */ -t_pdp_dpd_command *pdp_dpd_commandfactory_get_new_command(t_pdp_dpd_commandfactory *x) -{ - - t_pdp_dpd_command *c = x->command; - t_pdp_dpd_command *oldhead = c; - - /* check if we can reuse */ - while (c){ - if (!c->used){ - c->used = 1; - //post("reusing command %x", c, c->used); - return c; - } - //post("command %x is used %d", c, c->used); - c = c->next; - } - - /* create a new command */ - x->command = (t_pdp_dpd_command *)pdp_alloc(x->command_size); - x->command->next = oldhead; - x->command->used = 1; - x->nb_commands++; - //post("created command %x, nbcommands: %d", x->command, x->nb_commands); - return x->command; - -} - - -/* (self)destructor */ -void pdp_dpd_command_suicide(void *x) -{ - t_pdp_dpd_command *c = (t_pdp_dpd_command *)x; - c->used = 0; - //post("command %x committed suicide %d", c, c->used); -} - - - - diff --git a/system/kernel/pdp_forth.c b/system/kernel/pdp_forth.c deleted file mode 100644 index 1764004..0000000 --- a/system/kernel/pdp_forth.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Pure Data Packet header file. Packet processor system - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdlib.h> -#include <math.h> -#include "pdp.h" -#include "pdp_forth.h" - -#define D if (0) - - - -t_pdp_stack *pdp_stack_new(void) {return pdp_list_new(0);} - -void pdp_stack_free(t_pdp_stack *s) { - pdp_tree_strip_packets(s); - pdp_list_free(s); -} - - -/* some stack manips */ -t_pdp_word_error pdp_stack_dup(t_pdp_stack *s) -{ - if (!s->first) return e_underflow; - pdp_list_add(s, s->first->t, s->first->w); - - /* copy it properly if its a packet */ - if (s->first->t == a_packet){ - s->first->w.w_packet = pdp_packet_copy_ro(s->first->w.w_packet); - } - return e_ok; -} - -t_pdp_word_error pdp_stack_drop(t_pdp_stack *s) -{ - if (!s->first) return e_underflow; - - /* delete it properly if its a packet */ - if (s->first->t == a_packet){ - pdp_packet_mark_unused(s->first->w.w_packet); - } - pdp_list_pop(s); - - return e_ok; -} - -t_pdp_word_error pdp_stack_over(t_pdp_stack *s) -{ - if (s->elements < 2) return e_underflow; - pdp_list_add(s, s->first->next->t, s->first->next->w); - - /* copy it properly if its a packet */ - if (s->first->t == a_packet){ - s->first->w.w_packet = pdp_packet_copy_ro(s->first->w.w_packet); - } - - return e_ok; -} - -t_pdp_word_error pdp_stack_swap(t_pdp_stack *s) -{ - t_pdp_word w; - t_pdp_word_type t; - if (s->elements < 2) return e_underflow; - w = s->first->w; - t = s->first->t; - s->first->w = s->first->next->w; - s->first->t = s->first->next->t; - s->first->next->w = w; - s->first->next->t = t; - return e_ok; - -} - -/* pushing and popping the stack */ - -t_pdp_word_error pdp_stack_push_float(t_pdp_stack *s, float f) {pdp_list_add(s, a_float, (t_pdp_word)f); return e_ok;} -t_pdp_word_error pdp_stack_push_int(t_pdp_stack *s, int i) {pdp_list_add(s, a_int, (t_pdp_word)i); return e_ok;} -t_pdp_word_error pdp_stack_push_pointer(t_pdp_stack *s, void *x) {pdp_list_add(s, a_pointer, (t_pdp_word)x); return e_ok;} -t_pdp_word_error pdp_stack_push_symbol(t_pdp_stack *s, t_pdp_symbol *x) {pdp_list_add(s, a_symbol, (t_pdp_word)x); return e_ok;} - -/* note: packets pushed stack are owned by the stack. if a caller wants to keep a packet that - will be deleted by the word, it should make a copy before transferring it to the stack. - if a stack processor wants to write to a packet, it should replace it with a writable copy first */ - -t_pdp_word_error pdp_stack_push_packet(t_pdp_stack *s, int p) {pdp_list_add(s, a_packet, (t_pdp_word)p); return e_ok;} - - - - - -t_pdp_word_error pdp_stack_pop_float(t_pdp_stack *s, float *f) -{ - if (!s->first) return e_underflow; - - if (s->first->t == a_float) *f = s->first->w.w_float; - else if (s->first->t == a_int) *f = (float)s->first->w.w_int; - else *f = 0.0f; - pdp_stack_drop(s); - return e_ok; -} - -t_pdp_word_error pdp_stack_pop_int(t_pdp_stack *s, int *i) -{ - if (!s->first) return e_underflow; - if (s->first->t == a_int) *i = s->first->w.w_int; - else if (s->first->t == a_float) *i = (int)s->first->w.w_float; - else *i = 0; - pdp_stack_drop(s); - return e_ok; -} - -t_pdp_word_error pdp_stack_pop_pointer(t_pdp_stack *s, void **x) -{ - if (!s->first) return e_underflow; - *x = (s->first->t == a_pointer) ? s->first->w.w_pointer : 0; - pdp_stack_drop(s); - return e_ok; -} - -t_pdp_word_error pdp_stack_pop_symbol(t_pdp_stack *s, t_pdp_symbol **x) -{ - if (!s->first) return e_underflow; - *x = (s->first->t == a_symbol) ? s->first->w.w_symbol : pdp_gensym("invalid"); - pdp_stack_drop(s); - return e_ok; -} - -/* packets popped from the stack are owned by the caller */ - -t_pdp_word_error pdp_stack_pop_packet(t_pdp_stack *s, int *p) -{ - if (!s->first) return e_underflow; - *p = (s->first->t == a_packet) ? s->first->w.w_packet : -1; - pdp_list_pop(s); //ownership is transferred to receiver, drop kills the packet - return e_ok; -} - - -t_pdp_word_error pdp_stack_mov(t_pdp_stack *s) -{ - int position; - t_pdp_atom *a, *a_before; - if (s->elements < 2) return e_underflow; - if (s->first->t != a_int) return e_type; - - pdp_stack_pop_int(s, &position); // get insert point - if (position < 1) return e_ok; // < 0 : invalid; do nothing, 0 : nop (= insert at start, but already at start) - if ((s->elements-1) < position) return e_underflow; - - a = s->first; // get first atom - s->first = a->next; - - if (s->elements-1 == position){ //insert at end - s->last->next = a; - a->next = 0; - s->last = a; - } - else { //insert somewhere in the middle - a_before = s->first; - while (--position) a_before = a_before->next; - a->next = a_before->next; - a_before->next = a; - } - return e_ok; -} - -/* rotate stack down (tos -> bottom) */ -t_pdp_word_error pdp_stack_rdown(t_pdp_stack *s) -{ - t_pdp_word_type t = s->first->t; - t_pdp_word w = s->first->w; - pdp_list_pop(s); - pdp_list_add_back(s, t, w); - return e_ok; -} - - -/* convert to int */ -t_pdp_word_error pdp_stack_int(t_pdp_stack *s) -{ - int i; - pdp_stack_pop_int(s, &i); - pdp_stack_push_int(s, i); - return e_ok; -} - -/* convert to float */ -t_pdp_word_error pdp_stack_float(t_pdp_stack *s) -{ - float f; - pdp_stack_pop_float(s, &f); - pdp_stack_push_float(s, f); - return e_ok; -} - - -#define OP1(name, type, op) \ -t_pdp_word_error pdp_stack_##name##_##type (t_pdp_stack *s) \ -{ \ - type x0; \ - pdp_stack_pop_##type (s, &(x0)); \ - pdp_stack_push_##type (s, op (x0)); \ - return e_ok; \ -} - -#define OP2(name, type, op) \ -t_pdp_word_error pdp_stack_##name##_##type (t_pdp_stack *s) \ -{ \ - type x0, x1; \ - pdp_stack_pop_##type (s, &(x0)); \ - pdp_stack_pop_##type (s, &(x1)); \ - pdp_stack_push_##type (s, x1 op x0); \ - return e_ok; \ -} - -/* some floating point and integer stuff */ - -OP2(add, float, +); -OP2(sub, float, -); -OP2(mul, float, *); -OP2(div, float, /); - -OP1(sin, float, sin); -OP1(cos, float, cos); - -OP2(add, int, +); -OP2(sub, int, -); -OP2(mul, int, *); -OP2(div, int, /); -OP2(mod, int, %); - -OP2(and, int, &); -OP2(or, int, |); -OP2(xor, int, ^); - - -/* some integer stuff */ - -t_pdp_word_error pdp_stack_push_invalid_packet(t_pdp_stack *s) -{ - pdp_stack_push_packet(s, -1); - return e_ok; -} - -/* dictionary manipulation */ - -void pdp_forth_word_print_debug(t_pdp_symbol *s) -{ - t_pdp_atom *a; - if (!s->s_word_spec){ - post("%s is not a forth word", s->s_name); - } - else{ - post(""); - post("forth word %s", s->s_name); - post("\tinput: %d", s->s_word_spec->input_size); - post("\toutput: %d", s->s_word_spec->output_size); - post("\ttype index: %d", s->s_word_spec->type_index); - - post("\nimplementations:"); - for(a=s->s_word_spec->implementations->first; a; a=a->next){ - t_pdp_forthword_imp *i = a->w.w_pointer; - startpost("\t%s\t", i->type ? i->type->s_name : "anything"); - pdp_list_print(i->def); - - } - post(""); - } -} - -/* add a definition (list of high level words (symbols) or primitive routines) */ -void pdp_forthdict_add_word(t_pdp_symbol *name, t_pdp_list *def, int input_size, int output_size, - int type_index, t_pdp_symbol *type) -{ - t_pdp_forthword_spec *spec = 0; - t_pdp_forthword_imp *imp = 0; - t_pdp_forthword_imp *old_imp = 0; - t_pdp_atom *a; - /* check if the word complies to a previously defined word spec with the same name */ - if (spec = name->s_word_spec){ - if ((spec->input_size != input_size) - ||(spec->output_size != output_size) - ||(spec->type_index != type_index)){ - post("ERROR: pdp_forthdict_add_word: new implementation of [%s] does not comply to old spec", - name->s_name); - return; - } - - } - /* no previous word spec with this name, so create a new spec */ - else{ - spec = name->s_word_spec = (t_pdp_forthword_spec *)pdp_alloc(sizeof(t_pdp_forthword_spec)); - spec->name = name; - spec->input_size = input_size; - spec->output_size = output_size; - spec->type_index = type_index; - spec->implementations = pdp_list_new(0); - } - - /* create the new implementation and add it */ - imp = (t_pdp_forthword_imp *)pdp_alloc(sizeof(t_pdp_forthword_imp)); - imp->name = name; - imp->def = def; - imp->type = type; - - /* can't delete old implemetations because of thread safety */ - pdp_list_add_pointer(spec->implementations, imp); - -} - -/* add a primitive */ -void pdp_forthdict_add_primitive(t_pdp_symbol *name, t_pdp_forthword w, int input_size, int output_size, - int type_index, t_pdp_symbol *type) -{ - t_pdp_list *def = pdp_list_new(1); - def->first->t = a_pointer; - def->first->w.w_pointer = w; - pdp_forthdict_add_word(name, def, input_size, output_size, type_index, type); -} - -/* parse a new definition from a null terminated string */ -t_pdp_list *pdp_forth_compile_def(char *chardef) -{ - t_pdp_list *l; - char *c; - - if (!(l = pdp_list_from_cstring(chardef, &c))){ - post ("ERROR: pdp_forth_compile_def: parse error parsing: %s", chardef); - if (*c) post ("ERROR: remaining input: %s", c); - } - if (*c){ - post ("WARNING: pdp_forth_compile_def: parsing: %s", chardef); - if (*c) post ("garbage at end of string: %s", c); - } - - return l; - -} - -void pdp_forthdict_compile_word(t_pdp_symbol *name, char *chardef, int input_size, int output_size, - int type_index, t_pdp_symbol *type) -{ - /* add the definition list to the dictionary */ - t_pdp_list *def; - - if (def = pdp_forth_compile_def (chardef)) - pdp_forthdict_add_word(name, def, input_size, output_size, type_index, type); - - -} - - - -/* execute a definition list - a def list is a list of primitives, immediates or symbolic words */ -t_pdp_word_error pdp_forth_execute_def(t_pdp_stack *stack, t_pdp_list *def) -{ - t_pdp_atom *a; - t_pdp_word_error e; - t_pdp_forthword w; - float f; - int i,p; - - D post("pdp_forth_execute_def %x %x", stack, def); - D pdp_list_print(def); - - for (a = def->first; a; a=a->next){ - switch(a->t){ - case a_float: // an immidiate float - f = a->w.w_float; - D post("pushing %f onto the stack", f); - pdp_stack_push_float(stack, f); - break; - case a_int: // an immidiate int - i = a->w.w_int; - D post("pushing %d onto the stack", i); - pdp_stack_push_int(stack, i); - break; - case a_packet: // an immidiate int - p = a->w.w_packet; - D post("pushing packet %d onto the stack", p); - pdp_stack_push_packet(stack, pdp_packet_copy_ro(p)); - break; - case a_symbol: // a high level word or an immediate symbol - D post("interpeting symbol %s", a->w.w_symbol->s_name); - if (e = pdp_forth_execute_word(stack, a->w.w_symbol)) return e; - break; - case a_pointer: // a primitive - w = a->w.w_pointer; - D post("exec primitive %x", w); - if (e = (w(stack))) return e; - break; - default: - return e_internal; - - } - } - return e_ok; -} - -/* execute a symbol (a high level word or an immediate) - this routine does the type based word multiplexing and stack checking */ -t_pdp_word_error pdp_forth_execute_word(t_pdp_stack *stack, t_pdp_symbol *word) -{ - t_pdp_symbol *type = 0; - t_pdp_atom *a; - t_pdp_forthword_spec *spec; - t_pdp_forthword_imp *imp = 0; - int i; - - D post("pdp_forth_execute_word %x %x", stack, word); - - /* first check if the word is defined. if not, the symbol will be loaded - onto the stack as an immidiate symbol */ - - if (!(spec = word->s_word_spec)){ - D post ("pushing symbol %s on the stack", word->s_name); - pdp_stack_push_symbol(stack, word); - return e_ok; - } - - D post("exec high level word [%s]", word->s_name); - - /* it is a word. check the stack size */ - if (stack->elements < spec->input_size){ - D post ("error executing [%s]: stack underflow", word->s_name); - return e_underflow; - } - - /* if the word is type oblivious, symply execute the first (only) - implementation in the list */ - if (spec->type_index < 0){ - D post("exec type oblivious word [%s]", word->s_name); - imp = spec->implementations->first->w.w_pointer; - return pdp_forth_execute_def(stack , imp->def); - } - - /* if it is not type oblivious, find the type template - to determine the correct implementation */ - - for(i=spec->type_index,a=stack->first; i--; a=a->next); - switch (a->t){ - /* get type description from first item on*/ - case a_packet: - type = pdp_packet_get_description(a->w.w_packet); break; - case a_symbol: - type = a->w.w_symbol; break; - case a_float: - type = pdp_gensym("float"); break; - case a_int: - type = pdp_gensym("int"); break; - case a_pointer: - type = pdp_gensym("pointer"); break; - default: - /* no type description found on top of stack. */ - type = pdp_gensym("unknown"); - break; - } - - /* scan the implementation list until a definition with matching type is found - if the type spec for a word is NULL, it counts as a match (for generic words) */ - for (a = spec->implementations->first; a; a = a->next){ - imp = a->w.w_pointer; - if ((!imp->type) || pdp_type_description_match(type, imp->type)){ - return pdp_forth_execute_def(stack , imp->def); - } - } - D post("ERROR: pdp_forth_execute_word: type error executing [%s] (2). stack:",word->s_name); - D pdp_list_print(stack); - - return e_type; // type error - -} - - -static void _add_2op(char *name, t_pdp_forthword w, char *type){ - pdp_forthdict_add_primitive(pdp_gensym(name), w, 2, 1, 0, pdp_gensym(type)); -} - -static void _add_1op(char *name, t_pdp_forthword w, char *type){ - pdp_forthdict_add_primitive(pdp_gensym(name), w, 1, 1, 0, pdp_gensym(type)); -} - - -void pdp_forth_setup(void) -{ - - /* add type oblivious (type_index = -1, type = NULL) stack manip primitives */ - pdp_forthdict_add_primitive(pdp_gensym("dup"), (t_pdp_forthword)pdp_stack_dup, 1, 2, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("swap"), (t_pdp_forthword)pdp_stack_swap, 2, 2, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("drop"), (t_pdp_forthword)pdp_stack_drop, 1, 0, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("over"), (t_pdp_forthword)pdp_stack_over, 2, 3, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("mov"), (t_pdp_forthword)pdp_stack_mov, 2, 1, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("down"), (t_pdp_forthword)pdp_stack_rdown, 1, 1, -1, 0); - - /* type converters (casts) */ - pdp_forthdict_add_primitive(pdp_gensym("int"), (t_pdp_forthword)pdp_stack_int, 1, 1, -1, 0); - pdp_forthdict_add_primitive(pdp_gensym("float"), (t_pdp_forthword)pdp_stack_float, 1, 1, -1, 0); - - /* add floating point ops */ - _add_2op("add", (t_pdp_forthword)pdp_stack_add_float, "float"); - _add_2op("sub", (t_pdp_forthword)pdp_stack_sub_float, "float"); - _add_2op("mul", (t_pdp_forthword)pdp_stack_mul_float, "float"); - _add_2op("div", (t_pdp_forthword)pdp_stack_div_float, "float"); - - _add_1op("sin", (t_pdp_forthword)pdp_stack_sin_float, "float"); - _add_1op("cos", (t_pdp_forthword)pdp_stack_cos_float, "float"); - - /* add integer ops */ - _add_2op("add", (t_pdp_forthword)pdp_stack_add_int, "int"); - _add_2op("sub", (t_pdp_forthword)pdp_stack_sub_int, "int"); - _add_2op("mul", (t_pdp_forthword)pdp_stack_mul_int, "int"); - _add_2op("div", (t_pdp_forthword)pdp_stack_div_int, "int"); - _add_2op("mod", (t_pdp_forthword)pdp_stack_mod_int, "int"); - - _add_2op("and", (t_pdp_forthword)pdp_stack_and_int, "int"); - _add_2op("or", (t_pdp_forthword)pdp_stack_or_int, "int"); - _add_2op("xor", (t_pdp_forthword)pdp_stack_xor_int, "int"); - - /* some immidiates */ - pdp_forthdict_add_primitive(pdp_gensym("ip"), (t_pdp_forthword)pdp_stack_push_invalid_packet, 0, 1, -1, 0); - -} diff --git a/system/kernel/pdp_list.c b/system/kernel/pdp_list.c deleted file mode 100644 index ed2ad76..0000000 --- a/system/kernel/pdp_list.c +++ /dev/null @@ -1,663 +0,0 @@ - -/* - * Pure Data Packet header file. List class - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* who can live without a list, hmm? */ - -/* rethink the list of list thing: - should free and copy really copy the lists, or should - references to lists be allowed too? - - maybe references to lists as generic pointers? */ - -#include "pdp_list.h" -#include "pdp_types.h" -#include "pdp.h" -#include <pthread.h> -#include <stdlib.h> - -#define D if (0) - -#define PDP_LIST_BLOCKSIZE 4096 - -#define PDP_ATOM_ALLOC _pdp_atom_reuse -#define PDP_ATOM_DEALLOC _pdp_atom_save -//#define PDP_ATOM_ALLOC _pdp_atom_alloc -//#define PDP_ATOM_DEALLOC _pdp_atom_dealloc - -static t_pdp_atom *freelist; -static t_pdp_list *blocklist; -static pthread_mutex_t mut; - -/* memory allocation (for ease of wrapping) */ -static inline t_pdp_list* _pdp_list_alloc(void){return (t_pdp_list *)pdp_alloc(sizeof(t_pdp_list));} -static inline void _pdp_list_dealloc(t_pdp_list *list){pdp_dealloc(list);} -static inline t_pdp_atom* _pdp_atom_alloc(void){return (t_pdp_atom *)pdp_alloc(sizeof(t_pdp_atom));} -static inline void _pdp_atom_dealloc(t_pdp_atom *a){pdp_dealloc(a);} - - - -/* some private helper methods */ - -/* list pool setup */ -void pdp_list_setup(void) -{ - freelist = 0; - blocklist = _pdp_list_alloc(); - blocklist->elements = 0; - blocklist->first = 0; - pthread_mutex_init(&mut, NULL); - -#if 0 - { - char *c = "(test 1 2 (23 4)) (een (zes (ze)ven ()))) (())"; - while (*c){ - t_pdp_list *l = pdp_list_from_char(c, &c); - if (l) pdp_list_print(l); - else{ - post("parse error: remaining input: %s", c); break; - } - } - } -#endif - -} - -/* allocate a block */ -static t_pdp_atom* _pdp_atom_block_alloc(int size) -{ - int i = size; - t_pdp_atom *atom_block, *atom; - atom_block = (t_pdp_atom *)pdp_alloc(sizeof(t_pdp_atom) * size); - atom = atom_block; - while(i--){ - atom->next = atom + 1; - atom->t = a_undef; - atom->w.w_int = 0; - atom++; - } - atom_block[size-1].next = 0; - return atom_block; -} - -static void _pdp_atomlist_fprint(FILE* f, t_pdp_atom *a); - -static void _pdp_atom_refill_freelist(void) -{ - t_pdp_atom *atom; - - if (freelist != 0) post("ERROR:_pdp_atom_do_reuse: freelist != 0"); - - /* get a new block */ - freelist = _pdp_atom_block_alloc(PDP_LIST_BLOCKSIZE); - //post("new block"); - //_pdp_atomlist_fprint(stderr, freelist); - - /* take the first element from the block to serve as a blocklist element */ - atom = freelist; - atom->t = a_pointer; - atom->w.w_pointer = freelist; - freelist = freelist->next; - atom->next = blocklist->first; - blocklist->first = atom; - blocklist->elements++; - -} - - -/* reuse an old element from the freelist, or allocate a new block */ -static inline t_pdp_atom* _pdp_atom_reuse(void) -{ - t_pdp_atom *atom; - - pthread_mutex_lock(&mut); - - while (!(atom = freelist)){ - _pdp_atom_refill_freelist(); - } - /* delete the element from the freelist */ - freelist = freelist->next; - atom->next = 0; - - pthread_mutex_unlock(&mut); - - return atom; -} - -static inline void _pdp_atom_save(t_pdp_atom *atom) -{ - pthread_mutex_lock(&mut); - - atom->next = freelist; - freelist = atom; - - pthread_mutex_unlock(&mut); -} - - - - - - -/* create a list */ -t_pdp_list* pdp_list_new(int elements) -{ - t_pdp_atom *a = 0; - t_pdp_list *l = _pdp_list_alloc(); - l->elements = 0; - if (elements){ - a = PDP_ATOM_ALLOC(); - l->elements++; - a->t = a_undef; - a->w.w_int = 0; - a->next = 0; - elements--; - } - l->first = a; - l->last = a; - - while (elements--){ - a = PDP_ATOM_ALLOC(); - l->elements++; - a->t = a_undef; - a->w.w_int = 0; - a->next = l->first; - l->first = a; - } - return l; -} - -/* clear a list */ -void pdp_list_clear(t_pdp_list *l) -{ - t_pdp_atom *a = l->first; - t_pdp_atom *next_a; - - while(a){ - next_a = a->next; - PDP_ATOM_DEALLOC(a); - a = next_a; - } - l->first = 0; - l->last = 0; - l->elements = 0; -} - -/* destroy a list */ -void pdp_list_free(t_pdp_list *l) -{ - if (l){ - pdp_list_clear(l); - _pdp_list_dealloc(l); - } -} - - -/* destroy a (sub)tree */ -void pdp_tree_free(t_pdp_list *l) -{ - if (l) { - pdp_tree_clear(l); - _pdp_list_dealloc(l); - } -} - -/* clear a tree */ -void pdp_tree_clear(t_pdp_list *l) -{ - t_pdp_atom *a = l->first; - t_pdp_atom *next_a; - - while(a){ - if (a->t == a_list) pdp_tree_free(a->w.w_list); - next_a = a->next; - PDP_ATOM_DEALLOC(a); - a = next_a; - } - l->first = 0; - l->last = 0; - l->elements = 0; -} - - -static inline int _is_whitespace(char c){return (c == ' ' || c == '\n' || c == '\t');} -static inline void _skip_whitespace(char **c){while (_is_whitespace(**c)) (*c)++;} -static inline int _is_left_separator(char c) {return (c == '(');} -static inline int _is_right_separator(char c) {return (c == ')');} -static inline int _is_separator(char c) {return (_is_left_separator(c) || _is_right_separator(c) || _is_whitespace(c));} - - -static inline void _parse_atom(t_pdp_word_type *t, t_pdp_word *w, char *c, int n) -{ - char tmp[n+1]; - //post("_parse_atom(%d, %x, %s, %d)", *t, w, c, n); - strncpy(tmp, c, n); - tmp[n] = 0; - - - /* check if it's a number */ - if (tmp[0] >= '0' && tmp[0] <= '9'){ - int is_float = 0; - char *t2; - for(t2 = tmp; *t2; t2++){ - if (*t2 == '.') { - is_float = 1; - break; - } - } - /* it's a float */ - if (is_float){ - float f = strtod(tmp, 0); - D post("adding float %f", f); - *t = a_float; - *w = (t_pdp_word)f; - } - - /* it's an int */ - else { - int i = strtol(tmp, 0, 0); - D post("adding int %d", i); - *t = a_int; - *w = (t_pdp_word)i; - } - - } - /* it's a symbol */ - else { - D post("adding symbol %s", tmp); - *t = a_symbol; - *w = (t_pdp_word)pdp_gensym(tmp); - } - - D post("done parsing atom"); - -} - - -/* create a list from a character string */ -t_pdp_list *pdp_list_from_cstring(char *chardef, char **nextchar) -{ - t_pdp_list *l = pdp_list_new(0); - char *c = chardef; - char *lastname = c; - int n = 0; - - D post ("creating list from char: %s", chardef); - - /* find opening parenthesis and skip it*/ - _skip_whitespace(&c); - if (!_is_left_separator(*c)) goto error; else c++; - - /* start counting at the first non-whitespace - character after opening parenthesis */ - _skip_whitespace(&c); - lastname = c; - n = 0; - - while(*c){ - if (!_is_separator(*c)){ - /* item not terminated: keep counting */ - c++; - n++; - } - else { - /* separator encountered whitespace or parenthesis */ - - if (n){ - /* if there was something between this and the previous - separator, we've found and atom and parse it */ - pdp_list_add_back(l, a_undef, (t_pdp_word)0); - _parse_atom(&l->last->t, &l->last->w, lastname, n); - - /* skip the whitespace after the parsed word, if any */ - _skip_whitespace(&c); - } - - /* if we're at a right separator, we're done */ - if (_is_right_separator(*c)) {c++; goto done;} - - /* if it's a left separater, we have a sublist */ - if (_is_left_separator(*c)){ - t_pdp_list *sublist = pdp_list_from_cstring(c, &c); - if (!sublist) goto error; //sublist had parse error - pdp_list_add_back(l, a_list, (t_pdp_word)sublist); - } - - /* prepare for next atom */ - lastname = c; - n = 0; - } - - } - - error: - /* end of string encountered: parse error */ - D post("parse error: %s", c); - if (nextchar) *nextchar = c; - pdp_tree_free(l); //this will free all sublists too - return 0; - - - done: - _skip_whitespace(&c); - if (nextchar) *nextchar = c; - return l; - - - -} - - -/* traversal */ -void pdp_list_apply(t_pdp_list *l, t_pdp_atom_method m) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next) m(a); -} - -void pdp_tree_apply(t_pdp_list *l, t_pdp_atom_method m) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == a_list) pdp_tree_apply(a->w.w_list, m); - else m(a); - } -} - -void pdp_list_apply_word_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_word_method wm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == type) wm(a->w); - } -} -void pdp_list_apply_pword_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_pword_method pwm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == type) pwm(&a->w); - } -} - -void pdp_tree_apply_word_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_word_method wm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == a_list) pdp_tree_apply_word_method(a->w.w_list, type, wm); - else if (a->t == type) wm(a->w); - } -} -void pdp_tree_apply_pword_method(t_pdp_list *l, - t_pdp_word_type type, t_pdp_pword_method pwm) -{ - t_pdp_atom *a; - if (!l) return; - for (a=l->first; a; a=a->next){ - if (a->t == a_list) pdp_tree_apply_pword_method(a->w.w_list, type ,pwm); - else if (a->t == type) pwm(&a->w); - } -} - -static void _atom_packet_mark_unused(t_pdp_atom *a) -{ - if (a->t == a_packet){ - pdp_packet_mark_unused(a->w.w_packet); - a->t = a_undef; - a->w.w_int = 0; - } -} - -void pdp_tree_strip_packets (t_pdp_list *l) -{ - pdp_tree_apply(l, _atom_packet_mark_unused); -} - - -/* debug */ -static void _pdp_atomlist_fprint(FILE* f, t_pdp_atom *a) -{ - fprintf(f, "("); - while (a){ - switch(a->t){ - case a_symbol: fprintf(f, "%s",a->w.w_symbol->s_name); break; - case a_float: fprintf(f, "%f",a->w.w_float); break; - case a_int: fprintf(f, "%d",a->w.w_int); break; - case a_packet: fprintf(f, "#<pdp %d %s>",a->w.w_packet, - pdp_packet_get_description(a->w.w_packet)->s_name); break; - case a_pointer: fprintf(f, "#<0x%08x>",(unsigned int)a->w.w_pointer); break; - case a_list: _pdp_atomlist_fprint(f, a->w.w_list->first); break; - case a_undef: fprintf(f, "undef"); break; - - default: fprintf(f, "unknown"); break; - } - a = a->next; - if (a) fprintf(f, " "); - } - fprintf(f, ")"); -} - -void _pdp_list_fprint(FILE* f, t_pdp_list *l) -{ - _pdp_atomlist_fprint(f, l->first); - fprintf(f, "\n"); -} - -void pdp_list_print(t_pdp_list *l) -{ - _pdp_list_fprint(stderr, l); -} - - -/* public list operations */ - - -/* add a word to the start of the list */ -void pdp_list_add(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom *new_a = PDP_ATOM_ALLOC(); - l->elements++; - new_a->next = l->first; - new_a->w = w; - new_a->t = t; - l->first = new_a; - if (!l->last) l->last = new_a; -} - - -/* add a word to the end of the list */ -void pdp_list_add_back(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom *new_a = PDP_ATOM_ALLOC(); - l->elements++; - new_a->next = 0; - new_a->w = w; - new_a->t = t; - if (l->last){ - l->last->next = new_a; - } - else{ - l->first = new_a; - } - l->last = new_a; -} - -/* get list size */ -int pdp_list_size(t_pdp_list *l) -{ - return l->elements; -} - - - - -/* pop: return first item and remove */ -t_pdp_word pdp_list_pop(t_pdp_list *l) -{ - t_pdp_atom *a = l->first; - t_pdp_word w; - - w = a->w; - l->first = a->next; - PDP_ATOM_DEALLOC(a); - l->elements--; - if (!l->first) l->last = 0; - - return w; -} - - -/* return element at index */ -t_pdp_word pdp_list_index(t_pdp_list *l, int index) -{ - t_pdp_atom *a; - for (a = l->first; index--; a = a->next); - return a->w; -} - - - - - -/* remove an element from a list */ -void pdp_list_remove(t_pdp_list *l, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom head; - t_pdp_atom *a; - t_pdp_atom *kill_a; - head.next = l->first; - - for(a = &head; a->next; a = a->next){ - if (a->next->w.w_int == w.w_int && a->next->t == t){ - kill_a = a->next; // element to be killed - a->next = a->next->next; // remove link - PDP_ATOM_DEALLOC(kill_a); - l->elements--; - l->first = head.next; // restore the start pointer - if (l->last == kill_a) { // restore the end pointer - l->last = (a != &head) ? a : 0; - } - - break; - } - } - -} - - - - - -/* copy a list */ -t_pdp_list* pdp_tree_copy_reverse(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(0); - t_pdp_atom *a; - for (a = list->first; a; a = a->next) - if (a->t == a_list){ - pdp_list_add(newlist, a->t, - (t_pdp_word)pdp_tree_copy_reverse(a->w.w_list)); - } - else{ - pdp_list_add(newlist, a->t, a->w); - } - return newlist; -} -t_pdp_list* pdp_list_copy_reverse(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(0); - t_pdp_atom *a; - for (a = list->first; a; a = a->next) - pdp_list_add(newlist, a->t, a->w); - return newlist; -} - -t_pdp_list* pdp_tree_copy(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(list->elements); - t_pdp_atom *a_src = list->first; - t_pdp_atom *a_dst = newlist->first; - - while(a_src){ - a_dst->t = a_src->t; - if (a_dst->t == a_list){ //recursively copy sublists (tree copy) - a_dst->w.w_list = pdp_tree_copy(a_src->w.w_list); - } - else{ - a_dst->w = a_src->w; - } - a_src = a_src->next; - a_dst = a_dst->next; - } - - return newlist; -} -t_pdp_list* pdp_list_copy(t_pdp_list *list) -{ - t_pdp_list *newlist = pdp_list_new(list->elements); - t_pdp_atom *a_src = list->first; - t_pdp_atom *a_dst = newlist->first; - - while(a_src){ - a_dst->t = a_src->t; - a_dst->w = a_src->w; - a_src = a_src->next; - a_dst = a_dst->next; - } - return newlist; -} - -void pdp_list_cat (t_pdp_list *l, t_pdp_list *tail) -{ - t_pdp_list *tmp = pdp_list_copy(tail); - l->elements += tmp->elements; - l->last->next = tmp->first; - l->last = tmp->last; - _pdp_list_dealloc(tmp); //delete the list stub - -} - - -/* check if a list contains an element */ -int pdp_list_contains(t_pdp_list *list, t_pdp_word_type t, t_pdp_word w) -{ - t_pdp_atom *a; - for(a = list->first; a; a=a->next){ - if (a->w.w_int == w.w_int && a->t == t) return 1; - } - return 0; -} - -/* add a thing to the start of the list if it's not in there already */ -void pdp_list_add_to_set(t_pdp_list *list, t_pdp_word_type t, t_pdp_word w) -{ - if (!pdp_list_contains(list, t, w)) - pdp_list_add(list, t, w); -} - - - diff --git a/system/kernel/pdp_mem.c b/system/kernel/pdp_mem.c deleted file mode 100644 index 33822ef..0000000 --- a/system/kernel/pdp_mem.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Pure Data Packet system file: memory allocation - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdlib.h> -#include "pdp_mem.h" -#include "pdp_debug.h" - - -/* malloc wrapper that calls garbage collector */ -void *pdp_alloc(int size) -{ - void *ptr = malloc(size); - - PDP_ASSERT(ptr); - - return ptr; - - //TODO: REPAIR THIS - //post ("malloc failed in a pdp module: running garbage collector."); - //pdp_pool_collect_garbage(); - //return malloc(size); -} - - -void pdp_dealloc(void *stuff) -{ - free (stuff); -} - - -/* fast atom allocation object - well, this is not too fast yet, but will be later - when it suports linux futexes or atomic operations */ - -//#include <pthread.h> - -/* private linked list struct */ -typedef struct _fastalloc -{ - struct _fastalloc * next; -} t_fastalloc; - - - - -static void _pdp_fastalloc_lock(t_pdp_fastalloc *x){pthread_mutex_lock(&x->mut);} -static void _pdp_fastalloc_unlock(t_pdp_fastalloc *x){pthread_mutex_unlock(&x->mut);} - -static void _pdp_fastalloc_refill_freelist(t_pdp_fastalloc *x) -{ - t_fastalloc *atom; - unsigned int i; - - PDP_ASSERT(x->freelist == 0); - - /* get a new block - there is no means of freeing the data afterwards, - this is a fast implementation with the tradeoff of data - fragmentation "memory leaks".. */ - - x->freelist = pdp_alloc(x->block_elements * x->atom_size); - - /* link all atoms together */ - atom = x->freelist; - for (i=0; i<x->block_elements-1; i++){ - atom->next = (t_fastalloc *)(((char *)atom) + x->atom_size); - atom = atom->next; - } - atom->next = 0; - -} - -void *pdp_fastalloc_new_atom(t_pdp_fastalloc *x) -{ - t_fastalloc *atom; - - _pdp_fastalloc_lock(x); - - /* get an atom from the freelist - or refill it and try again */ - while (!(atom = x->freelist)){ - _pdp_fastalloc_refill_freelist(x); - } - - /* delete the element from the freelist */ - x->freelist = x->freelist->next; - atom->next = 0; - - _pdp_fastalloc_unlock(x); - - return (void *)atom; - -} -void pdp_fastalloc_save_atom(t_pdp_fastalloc *x, void *atom) -{ - _pdp_fastalloc_lock(x); - ((t_fastalloc *)atom)->next = x->freelist; - x->freelist = (t_fastalloc *)atom; - _pdp_fastalloc_unlock(x); -} - -t_pdp_fastalloc *pdp_fastalloc_new(unsigned int size) -{ - t_pdp_fastalloc *x = pdp_alloc(sizeof(*x)); - if (size < sizeof(t_fastalloc)) size = sizeof(t_fastalloc); - x->freelist = 0; - x->atom_size = size; - x->block_elements = PDP_FASTALLOC_BLOCK_ELEMENTS; - pthread_mutex_init(&x->mut, NULL); - return x; -} - diff --git a/system/kernel/pdp_packet.c b/system/kernel/pdp_packet.c deleted file mode 100644 index a811381..0000000 --- a/system/kernel/pdp_packet.c +++ /dev/null @@ -1,957 +0,0 @@ -/* - * Pure Data Packet system implementation: Packet Manager - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include "pdp.h" -#include <stdio.h> -#include <pthread.h> -#include <unistd.h> -#include <string.h> - - -/* TODO: - implement an indexing system to the packet pool (array) to speed up searches. - -> a list of lists of recycled packes, arranged by packet type. - -> a list of unused slots -*/ - - - -#define D if (0) - -/* all symbols are C style */ -#ifdef __cplusplus -extern "C" -{ -#endif - - -/* pdp specific constants */ -#define PDP_ALIGN 8 - -/* this needs to be able to grow dynamically, think about it later */ -/* for ordinary work, this is enough and can help finding memory leaks */ - -#define PDP_INITIAL_POOL_SIZE 1 -#define PDP_PACKET_MAX_MEM_USAGE -1 - -/* the pool */ -static unsigned int pdp_packet_mem_usage; -static unsigned int pdp_packet_max_mem_usage; -static int pdp_pool_size; -static t_pdp** pdp_pool; - -/* this is for detecting memory leaks */ -static int pdp_packet_count; - -/* some global vars */ -static t_symbol* pdp_sym_register_rw; -static t_symbol* pdp_sym_register_ro; -static t_symbol* pdp_sym_process; - -/* mutex */ -static pthread_mutex_t pdp_pool_mutex; - -/* the list of classes */ -static t_pdp_list *class_list; - -/* debug */ -void -pdp_packet_print_debug(int packet) -{ - t_pdp *h = pdp_packet_header(packet); - post("debug info for packet %d", packet); - if (!h){ - post("invalid packet"); - } - else{ - post ("\ttype: %d", h->type); - post ("\tdesc: %s", h->desc ? h->desc->s_name : "unknown"); - post ("\tsize: %d", h->size); - post ("\tflags: %x", h->flags); - post ("\tusers: %d", h->users); - post ("\trefloc: %x", h->refloc); - post ("\tclass: %x", h->theclass); - } -} - - - -/* setup methods */ - -void -pdp_packet_setup(void) -{ - - pdp_pool_size = PDP_INITIAL_POOL_SIZE; - pdp_packet_count = 0; - pdp_packet_mem_usage = 0; - pdp_packet_max_mem_usage = PDP_PACKET_MAX_MEM_USAGE; - pdp_pool = (t_pdp **)malloc(PDP_INITIAL_POOL_SIZE * sizeof(t_pdp *)); - bzero(pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - pdp_sym_register_rw = gensym("register_rw"); - pdp_sym_register_ro = gensym("register_ro"); - pdp_sym_process = gensym("process"); - pdp_packet_count = 0; - class_list = pdp_list_new(0); - - pthread_mutex_init(&pdp_pool_mutex, NULL); -} - -/* class methods */ -t_pdp_class *pdp_class_new(t_pdp_symbol *type, t_pdp_factory_method create){ - t_pdp_class *c = (t_pdp_class *)pdp_alloc(sizeof(t_pdp_class)); - memset(c, 0, sizeof(t_pdp_class)); - c->create = create; - c->type = type; // set type - //c->attributes = pdp_list_new(0); // create an empty attribute list - pdp_list_add(class_list, a_pointer, (t_pdp_word)((void *)c)); - //post("added class %s %x", c->type->s_name, c->create); - - return c; -} - -#if 0 -void pdp_class_addmethod(t_pdp_class *c, t_pdp_symbol *name, t_pdp_attribute_method method, - t_pdp_list *in_spec, t_pdp_list *out_spec) -{ - t_pdp_attribute *attr = (t_pdp_attribute *)pdp_alloc(sizeof(t_pdp_attribute)); - attr->name = name; - attr->method = method; - attr->in_spec = in_spec; - attr->out_spec = out_spec; - pdp_list_add_pointer(c->attributes, attr); - -} -#endif - -/* the packet factory */ -int pdp_factory_newpacket(t_pdp_symbol *type) -{ - t_pdp_class *c; - t_pdp_atom *a = class_list->first; - while(a){ - c = (t_pdp_class *)(a->w.w_pointer); - if (c->type && pdp_type_description_match(type, c->type)){ - //post("method %x, type %s", c->create, type->s_name); - return (c->create) ? (*c->create)(type) : -1; - } - a = a->next; - } - return -1; -} - -#if 0 -/* generic methods. actually a forth word operation on a stack. - first item on stack must be a packet and it's type will - determine the place to look for the operator */ -int pdp_packet_op(t_pdp_symbol *operation, struct _pdp_list *stack) -{ - int packet = stack->first->w.w_packet; - t_pdp *h = pdp_packet_header(packet); - t_pdp_atom *i; - t_pdp_attribute *attr; - - if (!(h && h->theclass)) goto exit; - - PDP_POINTER_IN(h->theclass->attributes, i, attr){ - //post("attribute:%s", attr->name->s_name); - if (attr->name == operation){ - - /* FOUND -> exec (check arguments first ???) */ - return attr->method (stack); - } - - } - exit: - // method not found - post ("WARNING: pdp_packet_op: packet %d from class %s has no operation %s", - packet, (h && h->theclass) ? h->theclass->type->s_name : "UNKNOWN", operation->s_name); - return 0; -} - -#endif - -static void -_pdp_pool_expand(void){ - int i; - - /* double the size */ - int new_pool_size = pdp_pool_size << 1; - t_pdp **new_pool = (t_pdp **)malloc(new_pool_size * sizeof(t_pdp *)); - bzero(new_pool, new_pool_size * sizeof(t_pdp *)); - memcpy(new_pool, pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - free(pdp_pool); - pdp_pool = new_pool; - pdp_pool_size = new_pool_size; - - D post("DEBUG: _pdp_pool_expand: resized pool to contain %d packets", pdp_pool_size); -} - - - - -/* private _pdp_packet methods */ - -/* packets can only be created and destroyed using these 2 methods */ -/* it updates the mem usage and total packet count */ - -static void -_pdp_packet_dealloc(t_pdp *p) -{ - unsigned int size = p->size; - if (p->theclass && p->theclass->cleanup) - (*p->theclass->cleanup)(p); - - free (p); - pdp_packet_mem_usage -= size; - pdp_packet_count--; - D post("DEBUG: _pdp_packet_new_dealloc: freed packet. pool contains %d packets", pdp_packet_count); -} - -static t_pdp* -_pdp_packet_alloc(unsigned int datatype, unsigned int datasize) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - unsigned int align; - t_pdp *p = 0; - - /* check if there is a memory usage limit */ - if (pdp_packet_max_mem_usage){ - /* if it would exceed the limit, fail */ - if (pdp_packet_mem_usage + totalsize > pdp_packet_max_mem_usage){ - D post("DEBUG: _pdp_packet_new_alloc: memory usage limit exceeded"); - return 0; - } - } - p = (t_pdp *)malloc(totalsize); - if (p){ - align = ((unsigned int)p) & (PDP_ALIGN - 1); - if (align) post("WARNING: _pdp_packet_alloc: data misaligned by %x", align); - memset(p, 0, PDP_HEADER_SIZE); //initialize header to 0 - p->type = datatype; - p->size = totalsize; - p->users = 1; - pdp_packet_mem_usage += totalsize; - pdp_packet_count++; - D post("DEBUG: _pdp_packet_new_alloc: allocated new packet. pool contains %d packets, using %d bytes", - pdp_packet_count, pdp_packet_mem_usage); - } - - return p; -} - - -void -pdp_packet_destroy(void) -{ - int i = 0; - /* dealloc all the data in object stack */ - post("DEBUG: pdp_packet_destroy: clearing object pool."); - while ((i < pdp_pool_size) && (pdp_pool[i])) _pdp_packet_dealloc(pdp_pool[i++]); -} - - - -/* try to find a packet based on main type and datasize */ -static int -_pdp_packet_reuse_type_size(unsigned int datatype, unsigned int datasize) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - int i = 0; - int return_packet = -1; - t_pdp* p; - - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - /* check if we can reuse this one if it is already allocated */ - if (p) { - /* search for unused packets of equal size & type */ - if ((p->users == 0) && (p->size == totalsize) && (p->type == datatype)){ - D post("DEBUG: _pdp_packet_reuse_type_size: can reuse %d", i); - - /* if possible, a packet will be reused and reinitialized - i haven't found a use for this, so it's only used for discriminating - between pure and not-so-pure packets */ - if (p->theclass && p->theclass->reinit){ - (*p->theclass->reinit)(p); - } - /* if no re-init method is found, the header will be reset to all 0 - this ensures the header is in a predictable state */ - else { - memset(p, 0, PDP_HEADER_SIZE); - p->type = datatype; - p->size = totalsize; - } - - p->users = 1; - return_packet = i; - goto exit; - } - else{ - D post("DEBUG _pdp_packet_reuse_type_size: can't reuse %d, (%d users)", i, p->users); - } - } - } - - D post("DEBUG: _pdp_packet_reuse_type_size: no reusable packet found"); - - exit: - return return_packet; -} - - -/* create a new packet in an empty slot. - if this fails, the garbage collector needs to be called */ -static int -_pdp_packet_create_in_empty_slot(unsigned int datatype, unsigned int datasize /*without header*/) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - int i = 0; - int return_packet = -1; - int out_of_mem = 0; - t_pdp* p; - - - /* no reusable packets found, try to find an empty slot */ - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - if (!p) { - p = _pdp_packet_alloc(datatype, datasize); - - if (!p) { - D post("DEBUG: _pdp_packet_create_in_empty_slot: out of memory (malloc returned NULL)"); - return_packet = -1; - goto exit; - } - - pdp_pool[i] = p; - return_packet = i; - goto exit; - } - } - - /* if we got here the pool is full: resize the pool and try again */ - _pdp_pool_expand(); - return_packet = _pdp_packet_create_in_empty_slot(datatype, datasize); - - exit: - return return_packet; - -} - -/* find an unused packet, free it and create a new packet. - if this fails, something is seriously wrong */ -static int -_pdp_packet_create_in_unused_slot(unsigned int datatype, unsigned int datasize /*without header*/) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - int i = 0; - int return_packet = -1; - int out_of_mem = 0; - t_pdp* p; - - D post("DEBUG: _pdp_packet_create_in_unused_slot: collecting garbage"); - - /* search backwards */ - for (i=pdp_pool_size-1; i >= 0; i--){ - p = pdp_pool[i]; - if (p){ - if (p->users == 0){ - _pdp_packet_dealloc(p); - p = _pdp_packet_alloc(datatype, datasize); - pdp_pool[i] = p; - - /* alloc succeeded, return */ - if (p) { - post("DEBUG _pdp_packet_create_in_unused_slot: garbage collect succesful"); - return_packet = i; - goto exit; - } - - /* alloc failed, continue collecting garbage */ - D post("DEBUG _pdp_packet_create_in_unused_slot: freed one packet, still out of memory (malloc returned NULL)"); - out_of_mem = 1; - - } - } - } - - /* if we got here, we ran out of memory */ - D post("DEBUG: _pdp_packet_create_in_unused_slot: out of memory after collecting garbage"); - return_packet = -1; - -exit: - return return_packet; -} - -/* warning: for "not so pure" packets, this method will only return an initialized - packet if it can reuse a privious one. that is, if it finds a reinit method - in the packet. use the pdp_packet_new_<type> constructor if possible */ - -static int -_pdp_packet_brandnew(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int return_packet = -1; - - /* try to create a new packet in an empty slot */ - return_packet = _pdp_packet_create_in_empty_slot(datatype, datasize); - if (return_packet != -1) goto exit; - - /* if we still don't have a packet, we need to call the garbage collector until we can allocate */ - return_packet = _pdp_packet_create_in_unused_slot(datatype, datasize); - - exit: - return return_packet; -} - - -static int -_pdp_packet_new(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int return_packet = -1; - - /* try to reuse a packet based on main type and datasize */ - return_packet = _pdp_packet_reuse_type_size(datatype, datasize); - if (return_packet != -1) goto exit; - - /* create a brandnew packet */ - return_packet = _pdp_packet_brandnew(datatype, datasize); - if (return_packet != -1) goto exit; - - post("WARNING: maximum packet memory usage limit (%d bytes) reached after garbage collect.", pdp_packet_max_mem_usage); - post("WARNING: increase memory limit or decrease packet usage (i.e. pdp_loop, pdp_delay)."); - post("WARNING: pool contains %d packets, using %d bytes.", pdp_packet_count, pdp_packet_mem_usage); - - exit: - return return_packet; - -} - - - -/* public pool operations: have to be thread safe so each entry point - locks the mutex */ - -/* reuse an old packet based on high level description */ -int -pdp_packet_reuse(t_pdp_symbol *description) -{ - int i; - int return_packet = -1; - t_pdp *p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - /* check if we can reuse this one if it is already allocated */ - if ((p) && (p->users == 0) && (p->desc == description)){ - /* mark it as used */ - p->users = 1; - return_packet = i; - goto gotit; - } - } - - gotit: - /* LOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return return_packet; - - -} - -/* create a new packet, or reuse an old one based on main type and size */ -int -pdp_packet_new(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int packet; - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - packet = _pdp_packet_new(datatype, datasize); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - return packet; -} - - -/* create a brand new packet, don't reuse an old one */ -int -pdp_packet_brandnew(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int packet; - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - packet = _pdp_packet_brandnew(datatype, datasize); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - return packet; -} - - -/* this returns a copy of a packet for read only access. */ -int -pdp_packet_copy_ro(int handle) -{ - int out_handle = -1; - t_pdp* p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if ((handle >= 0) - && (handle < pdp_pool_size) - && (p = pdp_pool[handle])){ - - /* it is an error to copy a packet without an owner */ - if (!p->users){ - post("pdp_packet_copy_ro: ERROR: request to copy packet %d which has 0 users", handle); - out_handle = -1; - } - - /* if it's a passing packet, reset the reference location - and turn it into a normal packet */ - else if (p->refloc){ - *p->refloc = -1; - p->refloc = 0; - out_handle = handle; - } - /* if it's a normal packet, increase the number of users */ - else { - p->users++; - out_handle = handle; - } - } - else out_handle = -1; - - //post("pdp_copy_ro: outhandle:%d", out_handle); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return out_handle; -} - -/* copy a packet. if the packet is marked passing, it will be aquired. - otherwize a new packet will be created with a copy of the contents. */ - -int -pdp_packet_copy_rw(int handle) -{ - int out_handle = -1; - t_pdp* p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if ((handle >= 0) - && (handle < pdp_pool_size) - && (p = pdp_pool[handle])){ - /* if there are other users, copy the object otherwize return the same handle */ - - /* it is an error to copy a packet without an owner */ - if (!p->users){ - post("pdp_packet_copy_rw: ERROR: request to copy packet %d which has 0 users", handle); - out_handle = -1; - } - - /* if it is a passing packet, remove the owner's reference to it */ - else if (p->refloc){ - *p->refloc = -1; - p->refloc = 0; - out_handle = handle; - } - - /* check if packet supports copy (for fanout) */ - else if(p->flags & PDP_FLAG_DONOTCOPY) out_handle = -1; - - - /* copy the packet, since it already has 1 or more users */ - else{ - int new_handle = _pdp_packet_new(p->type, p->size - PDP_HEADER_SIZE); - t_pdp* new_p = pdp_packet_header(new_handle); - - /* check if valid */ - if (!new_p) out_handle = -1; - - else { - /* if a copy constructor is found, it will be called */ - if (p->theclass && p->theclass->copy){ - (*p->theclass->copy)(new_p, p); - } - /* if not, the entire packet will be copied, assuming a pure data packet */ - else { - memcpy(new_p, p, p->size); - } - new_p->users = 1; - out_handle = new_handle; - } - } - - //post("pdp_copy_rw: inhandle:%d outhandle:%d", handle, out_handle); - - } - else out_handle = -1; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - return out_handle; -} - -/* create a new packet, copying the header data of another - packet, without copying the data */ -int -pdp_packet_clone_rw(int handle) -{ - int out_handle; - t_pdp* p; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if ((handle >= 0) - && (handle < pdp_pool_size) - && (p = pdp_pool[handle])){ - - /* clone the packet header, don't copy the data */ - int new_handle = _pdp_packet_new(p->type, p->size - PDP_HEADER_SIZE); - t_pdp* new_p = pdp_packet_header(new_handle); - - /* if a clone initializer is found, it will be called */ - if (p->theclass && p->theclass->clone){ - (*p->theclass->clone)(new_p, p); - } - /* if not, just the header will be copied, assuming a pure data packet */ - else { - memcpy(new_p, p, PDP_HEADER_SIZE); - } - new_p->users = 1; /* the new packet has 1 user */ - new_p->refloc = 0; /* it is not a passing packet, even if the template was */ - out_handle = new_handle; - } - - else out_handle = -1; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return out_handle; -} - -void -_pdp_packet_mark_unused_nolock(int handle) -{ - t_pdp* p; - - if ((handle >= 0) && (handle < pdp_pool_size)){ - if (p = pdp_pool[handle]) { - /* mark_unused on a passing packet has no effect - this is to support automatic conversion for passing packets - so in order to delete a passing packet, it should be marked normal first */ - if (p->refloc){ - post("DEBUG: pdp_mark_unused called on a passing packet. ignored."); - return; - } - - /* decrease the refcount */ - if (p->users) { - p->users--; - //post("pdp_mark_unused: handle %d, users left %d", handle, p->users); - } - else { - post("pdp_mark_unused: ERROR: handle %d has zero users (duplicate pdp_mark_unused ?)", handle); - } - } - else { - post("pdp_mark_unused: ERROR: invalid handle %d: no associated object", handle); - } - } - - else { - /* -1 is the only invalid handle that doesn't trigger a warning */ - if (handle != -1) post("pdp_mark_unused: WARNING: invalid handle %d: out of bound", handle); - } - -} - -/* mark a packet as unused, decreasing the reference count. - if the reference count reaches zero, the packet is ready to be recycled - by a new packet allocation. it is illegal to reference a packet with - reference count == zero. if the reference count is not == 1, only readonly - access is permitted. */ - -void -pdp_packet_mark_unused(int handle) -{ - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - _pdp_packet_mark_unused_nolock(handle); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); -} - -void -pdp_packet_mark_unused_atomic(int *handle) -{ - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - _pdp_packet_mark_unused_nolock(*handle); - *handle = -1; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); -} - -/* delete a packet. this is more than mark_unused: - it actually removes any reference. can be used for - some packet types that have "expensive" resources. - usually this is up to the garbage collector to call. */ - -void -pdp_packet_delete(int handle) -{ - t_pdp *header = pdp_packet_header(handle); - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - - /* check if it's a valid handle */ - if ((handle >= 0) && (handle < pdp_pool_size) && pdp_pool[handle]){ - - /* mark it unused */ - _pdp_packet_mark_unused_nolock(handle); - - /* if no users, dealloc */ - if (!header->users){ - _pdp_packet_dealloc(header); - pdp_pool[handle] = NULL; - } - - /* print a warning if failed */ - else{ - post("WARNING: pdp_packet_delete: packet %d was not deleted. %d users remaining", - handle, header->users); - } - } - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - -} - - -/* this turns any packet into a normal (non-passing) packet */ - -void -pdp_packet_unmark_passing(int packet) -{ - t_pdp* header = pdp_packet_header(packet); - if (!header) return; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - header->refloc = 0; - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - -} - - -/* this marks a packet as passing. this means it changes - owner on first copy_ro or copy_rw. the previous owner is - notified by setting the handler to -1. */ - -void -pdp_packet_mark_passing(int *phandle) -{ - t_pdp* header = pdp_packet_header(*phandle); - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - if (header){ - if (header->refloc){ - post("pdp_packet_mark_passing: ERROR: duplicate mark_passing on packet %d", *phandle); - } - else if (1 != header->users){ - post("pdp_packet_mark_passing: ERROR: packet %d is not exclusively owned by caller, it has %d users", *phandle, header->users); - } - else { - header->refloc = phandle; - } - } - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - -} - - -/* public data access methods */ - -t_pdp* -pdp_packet_header(int handle) -{ - if ((handle >= 0) && (handle < pdp_pool_size)) return pdp_pool[handle]; - else return 0; -} - -void* -pdp_packet_subheader(int handle) -{ - t_pdp* header = pdp_packet_header(handle); - if (!header) return 0; - return (void *)(&header->info.raw); -} - -void* -pdp_packet_data(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return (char *)(h) + PDP_HEADER_SIZE; - } - else return 0; -} - - -/* OBSOLETE: use packet description */ -/* check if two packets are allocated and of the same type */ -bool pdp_packet_compat(int packet0, int packet1) -{ - - t_pdp *header0 = pdp_packet_header(packet0); - t_pdp *header1 = pdp_packet_header(packet1); - - if (!(header1)){ - //post("pdp_type_compat: invalid header packet1"); - return 0; - } - if (!(header0)){ - //post("pdp_type_compat: invalid header packet 0"); - return 0; - } - if (header0->type != header1->type){ - //post("pdp_type_compat: types do not match"); - return 0; - } - - return 1; -} - -int pdp_packet_writable(int packet) /* returns true if packet is writable */ -{ - t_pdp *h = pdp_packet_header(packet); - if (!h) return 0; - return (h->users == 1); -} - -void pdp_packet_replace_with_writable(int *packet) /* replaces a packet with a writable copy */ -{ - int new_p; - if (!pdp_packet_writable(*packet)){ - new_p = pdp_packet_copy_rw(*packet); - pdp_packet_mark_unused(*packet); - *packet = new_p; - } - -} - -/* pool stuff */ - -int -pdp_pool_collect_garbage(void) -{ - t_pdp *p; - int i; - int nbpackets = pdp_packet_count; - - /* LOCK */ - pthread_mutex_lock(&pdp_pool_mutex); - - for (i=0; i < pdp_pool_size; i++){ - p = pdp_pool[i]; - if(p && !p->users) { - _pdp_packet_dealloc(p); - pdp_pool[i] = 0; - } - } - nbpackets -= pdp_packet_count; - //post("pdp_pool_collect_garbage: deleted %d unused packets", nbpackets); - - /* UNLOCK */ - pthread_mutex_unlock(&pdp_pool_mutex); - - return nbpackets; -} - -void -pdp_pool_set_max_mem_usage(int max) -{ - if (max < 0) max = 0; - pdp_packet_max_mem_usage = max; - -} - - - - - - -/* malloc wrapper that calls garbage collector */ -void *pdp_alloc(int size) -{ - void *ptr = malloc(size); - - //post ("malloc called for %d bytes", size); - - if (ptr) return ptr; - - post ("malloc failed in a pdp module: running garbage collector."); - - pdp_pool_collect_garbage(); - return malloc(size); -} - - -void pdp_dealloc(void *stuff) -{ - free (stuff); -} - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_packet2.c b/system/kernel/pdp_packet2.c deleted file mode 100644 index 3717a77..0000000 --- a/system/kernel/pdp_packet2.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Pure Data Packet system implementation: Packet Manager - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - - -#include <stdio.h> -#include <pthread.h> -#include <unistd.h> -#include <string.h> -#include "pdp_post.h" -#include "pdp_packet.h" -#include "pdp_mem.h" -#include "pdp_list.h" -#include "pdp_type.h" -#include "pdp_debug.h" - - -/* packet implementation. contains class and packet (instance) handling - - some notes on packet operations. - copy ro/rw and unregister are relatively straightforward - packet creation can be done in 2 ways in this interface: - create + reuse - however, these methods should only be called by specific factory - methods, so the user should only create packets using pdp_factory_newpacket - - reuse or create is thus the responsability of the factory methods for - each packet type (class) implementation - - -*/ - - -/* NOTE: - the packet pool methods are called within the pool locks. this probably - needs to change, because it will cause deadlocks for container packets (fobs) */ - - -/* new implementation: probably just a minor adjustment: add the reuse fifo attached - to type desc symbol name - need to check and possibly eliminate hacks for non-pure packets - - pdp_packet_new: - LOCK - 1. check reuse fifo - 2. empty -> create packet+return (search array) - 3. element -> check if type is correct, yes->pop+return, no->goto 1. - UNLOCK - 4. wakeup - - pdp_packet_mark_unused - - 1. check refcount. if > 1 dec + exit - 2. if 1 put packet to sleep - 3. dec refcount - 4. add to reuse fifo (no fifo -> create) - - pdp_packet_delete: analogous to mark_unused - pdp_packet_copy_ro/rw: analogous to new - -*/ - - -/* the pool */ -#define PDP_INITIAL_POOL_SIZE 64 -static int pdp_pool_size; -static t_pdp** pdp_pool; - -/* mutex: protects the pool and reuse lists attached to symbols */ -static pthread_mutex_t pdp_pool_mutex; -#define LOCK pthread_mutex_lock (&pdp_pool_mutex) -#define UNLOCK pthread_mutex_unlock (&pdp_pool_mutex) - -/* the list of classes */ -static t_pdp_list *class_list; - -/* debug */ -void -pdp_packet_print_debug(int packet) -{ - t_pdp *h = pdp_packet_header(packet); - pdp_post("debug info for packet %d", packet); - if (!h){ - pdp_post("invalid packet"); - } - else{ - pdp_post ("\ttype: %d", h->type); - pdp_post ("\tdesc: %s", h->desc ? h->desc->s_name : "unknown"); - pdp_post ("\tsize: %d", h->size); - pdp_post ("\tflags: %x", h->flags); - pdp_post ("\tusers: %d", h->users); - pdp_post ("\tclass: %x", h->theclass); - } -} - - - -/* setup methods */ - -void -pdp_packet_setup(void) -{ - - pdp_pool_size = PDP_INITIAL_POOL_SIZE; - pdp_pool = (t_pdp **)pdp_alloc(PDP_INITIAL_POOL_SIZE * sizeof(t_pdp *)); - bzero(pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - class_list = pdp_list_new(0); - pthread_mutex_init(&pdp_pool_mutex, NULL); -} - -/* class methods */ -t_pdp_class *pdp_class_new(t_pdp_symbol *type, t_pdp_factory_method create){ - t_pdp_class *c = (t_pdp_class *)pdp_alloc(sizeof(t_pdp_class)); - memset(c, 0, sizeof(t_pdp_class)); - c->create = create; - c->type = type; // set type - pdp_list_add(class_list, a_pointer, (t_pdp_word)((void *)c)); - return c; -} - -/* the packet factory */ -int pdp_factory_newpacket(t_pdp_symbol *type) -{ - int p; - t_pdp_class *c; - t_pdp_atom *a = class_list->first; - - /* try to reuse first - THINK: should this be the responsability of the type specific constructors, - or should a packet allways be reusable (solution: depends on what the cleanup method returns??) - */ - p = pdp_packet_reuse(type); - if (-1 != p) return p; - - - /* call class constructor */ - while(a){ - c = (t_pdp_class *)(a->w.w_pointer); - if (c->type && pdp_type_description_match(type, c->type)){ - //pdp_post("method %x, type %s", c->create, type->s_name); - return (c->create) ? (*c->create)(type) : -1; - } - a = a->next; - } - return -1; -} - -static void -_pdp_pool_expand_nolock(void){ - int i; - - /* double the size */ - int new_pool_size = pdp_pool_size << 1; - t_pdp **new_pool = (t_pdp **)pdp_alloc(new_pool_size * sizeof(t_pdp *)); - bzero(new_pool, new_pool_size * sizeof(t_pdp *)); - memcpy(new_pool, pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - pdp_dealloc(pdp_pool); - pdp_pool = new_pool; - pdp_pool_size = new_pool_size; -} - - - - -/* private _pdp_packet methods */ - -/* packets can only be created and destroyed using these 2 methods */ -/* it updates the mem usage and total packet count */ - -static void -_pdp_packet_dealloc_nolock(t_pdp *p) -{ - /* free memory */ - pdp_dealloc (p); -} - -static t_pdp* -_pdp_packet_alloc_nolock(unsigned int datatype, unsigned int datasize) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - t_pdp *p = (t_pdp *)pdp_alloc(totalsize); - if (p){ - memset(p, 0, PDP_HEADER_SIZE); //initialize header to 0 - p->type = datatype; - p->size = totalsize; - p->users = 1; - } - return p; -} - - -/* create a new packet and expand pool if necessary */ -static int -_pdp_packet_create_nolock(unsigned int datatype, unsigned int datasize) -{ - int p = 0; - while(1){ - for (; p < pdp_pool_size; p++){ - if (!pdp_pool[p]){ - /* found slot to store packet*/ - t_pdp *header = _pdp_packet_alloc_nolock(datatype, datasize); - if (!header) return -1; // error allocating packet - pdp_pool[p] = header; - return p; - } - } - /* no slot found, expand pool */ - _pdp_pool_expand_nolock(); - } -} - - -void -pdp_packet_destroy(void) -{ - int i = 0; - /* dealloc all the data in object stack */ - pdp_post("DEBUG: pdp_packet_destroy: clearing object pool."); - while ((i < pdp_pool_size) && (pdp_pool[i])) _pdp_packet_dealloc_nolock(pdp_pool[i++]); -} - - - - - - - - -/* public pool operations: have to be thread safe so each entry point - locks the mutex */ - - -/* create a new packet. - this should only be used by type specific factory methods, and only if the - reuse method fails, since it will always create a new packet */ -int -pdp_packet_create(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int packet; - LOCK; - packet = _pdp_packet_create_nolock(datatype, datasize); - UNLOCK; - return packet; -} - - -/* return a new packet. - it tries to reuse a packet based on - 1. matching data size - 2. abscence of destructor (which SHOULD mean there are no enclosed references) - - it obviously can't use the reuse fifo tagged to a symbolic type description - - ALWAYS USE pdp_packet_reuse BEFORE calling pdp_packet_new if possible - use both ONLY IN CONSTRUCTORS !!! - - use pdp_packet_factory to create packets as a "user" - - this is a summary of all internal packet creation mechanisms: - - -> pdp_packet_reuse, which uses symbolic type descriptions, and should work for all packet types - it returns an initialized container (meta = correct, data = garbage) - - -> pdp_packet_new, which only works for non-pure packets, and reuses packets based on data type - it returns a pure packet (meta + data = garbage) - - -> pdp_packet_create, like pdp_packet_new, only it always creates a new packet - - - -*/ - -int -pdp_packet_new(unsigned int datatype, unsigned int datasize) -{ - t_pdp *header; - int packet; - LOCK; - for (packet = 0; packet < pdp_pool_size; packet++){ - header = pdp_pool[packet]; - /* check data size */ - if (header - && header->users == 0 - && header->size == datasize + PDP_HEADER_SIZE - && !(header->theclass && header->theclass->cleanup)){ - - /* ok, got one. initialize */ - memset(header, 0, PDP_HEADER_SIZE); - header->users = 1; - header->type = datatype; - header->size = datasize + PDP_HEADER_SIZE; - - UNLOCK; //EXIT1 - return packet; - } - } - - /* no usable non-pure packet found, create a new one */ - - UNLOCK; //EXIT2 - return pdp_packet_create(datatype, datasize); - - - -} - - -/* internal method to add a packet to a packet type - description symbol's unused packet fifo */ -void -_pdp_packet_save_nolock(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - t_pdp_symbol *s; - PDP_ASSERT(header); - PDP_ASSERT(header->users == 0); - PDP_ASSERT(header->desc); - s = header->desc; - if (!s->s_reusefifo) s->s_reusefifo = pdp_list_new(0); - pdp_list_add(s->s_reusefifo, a_packet, (t_pdp_word)packet); -} - -/* this will revive a packet matching a certain type description - no wildcards are allowed */ -int -pdp_packet_reuse(t_pdp_symbol *type_description) -{ - int packet = -1; - t_pdp *header = 0; - t_pdp_list *l = 0; - LOCK; - if (!type_description || !(l = type_description->s_reusefifo)) goto exit; - while(l->elements){ - packet = pdp_list_pop(l).w_packet; - header = pdp_packet_header(packet); - - /* check if reuse fifo is consistent (packet unused + correct type) - packet could be deleted and replaced with another one, or - revived without the index updated (it's a "hint cache") */ - - if (header->users == 0){ - /* check if type matches */ - if (pdp_type_description_match(header->desc, type_description)){ - header->users++; // revive - goto exit; - } - /* if not, add the packet to the correct reuse fifo */ - else{ - _pdp_packet_save_nolock(packet); - } - } - - /* remove dangling refs */ - header = 0; - packet = -1; - } - - exit: - UNLOCK; - if (header && header->theclass && header->theclass->wakeup){ - header->theclass->wakeup(header); // revive if necessary - } - return packet; -} - -/* find all unused packets in pool, marked as used (to protect from other reapers) - and return them as a list. non-pure packets are not revived */ - - - - - -/* this returns a copy of a packet for read only access. - (increases refcount of the packet -> packet will become readonly if it was - writable, i.e. had rc=1 */ - -int -pdp_packet_copy_ro(int handle) -{ - t_pdp* header; - - if (header = pdp_packet_header(handle)){ - PDP_ASSERT(header->users); // consistency check - LOCK; - header->users++; // increment reference count - UNLOCK; - } - else handle = -1; - return handle; -} - -/* clone a packet: create a new packet with the same - type as the source packet */ - -int -pdp_packet_clone_rw(int handle) -{ - t_pdp* header; - int new_handle = -1; - - - if (header = pdp_packet_header(handle)){ - /* consistency checks */ - PDP_ASSERT(header->users); - PDP_ASSERT(header->desc); - - /* first try to reuse old packet */ - new_handle = pdp_packet_reuse(header->desc); - - /* if this failed, create a new one using the central packet factory method */ - if (-1 == new_handle) new_handle = pdp_factory_newpacket(header->desc); - } - - return new_handle; -} - -/* return a copy of a packet (clone + copy data) */ -int -pdp_packet_copy_rw(int handle) -{ - t_pdp *header, *new_header; - int new_handle = -1; - - if (!(header = pdp_packet_header(handle))) return -1; - - /* check if we are allowed to copy */ - if (header->flags & PDP_FLAG_DONOTCOPY) return -1; - - /* get target packet */ - new_handle = pdp_packet_clone_rw(handle); - if (-1 == new_handle) return -1; - new_header = pdp_packet_header(new_handle); - - /* if there is a copy method, use that one */ - if (header->theclass && header->theclass->copy){ - header->theclass->copy(header, new_header); - } - - /* otherwize copy the data verbatim */ - else { - memcpy(pdp_packet_data(new_handle), - pdp_packet_data(handle), - pdp_packet_data_size(handle)); - } - - return new_handle; - -} - - -/* decrement refcount */ -void pdp_packet_mark_unused(int handle) -{ - t_pdp *header; - if (!(header = pdp_packet_header(handle))) return; - - PDP_ASSERT(header->users); // consistency check - - LOCK; - - /* just decrement refcount */ - if (header->users > 1){ - header->users--; - } - - /* put packet to sleep if refcount 1->0 */ - else { - if (header->theclass && header->theclass->sleep){ - /* call sleep method (if any) outside of lock - while the packet is still alive, so it won't be - acclaimed by another thread */ - UNLOCK; - header->theclass->sleep(header); - LOCK; - } - /* clear refcount & save in fifo for later use */ - header->users = 0; - if (header->desc) // sleep could have destructed packet.. - _pdp_packet_save_nolock(handle); - } - - UNLOCK; -} - - - -/* delete a packet. rc needs to be == 1 */ -void pdp_packet_delete(int handle) -{ - t_pdp *header; - header = pdp_packet_header(handle); - PDP_ASSERT(header); - PDP_ASSERT(header->users == 1); // consistency check - - LOCK; - - if (header->theclass && header->theclass->cleanup){ - /* call cleanup method (if any) outside of lock - while the packet is still alive, so it won't be - acclaimed by another thread */ - UNLOCK; - header->theclass->cleanup(header); - LOCK; - } - - /* delete the packet */ - pdp_pool[handle] = 0; - _pdp_packet_dealloc_nolock(header); - - - UNLOCK; -} - - - - - - - -/* public data access methods */ - -t_pdp* -pdp_packet_header(int handle) -{ - if ((handle >= 0) && (handle < pdp_pool_size)) return pdp_pool[handle]; - else return 0; -} - -void* -pdp_packet_subheader(int handle) -{ - t_pdp* header = pdp_packet_header(handle); - if (!header) return 0; - return (void *)(&header->info.raw); -} - -void* -pdp_packet_data(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return (char *)(h) + PDP_HEADER_SIZE; - } - else return 0; -} - -int -pdp_packet_data_size(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return h->size - PDP_HEADER_SIZE; - } - else return 0; -} - - - - -int pdp_packet_writable(int packet) /* returns true if packet is writable */ -{ - t_pdp *h = pdp_packet_header(packet); - if (!h) return 0; - return (h->users == 1); -} - -void pdp_packet_replace_with_writable(int *packet) /* replaces a packet with a writable copy */ -{ - int new_p; - if (!pdp_packet_writable(*packet)){ - new_p = pdp_packet_copy_rw(*packet); - pdp_packet_mark_unused(*packet); - *packet = new_p; - } - -} - -/* pool stuff */ - -int -pdp_pool_collect_garbage(void) -{ - pdp_post("ERROR: garbage collector not implemented"); - return 0; -} - -void -pdp_pool_set_max_mem_usage(int max) -{ - pdp_post("ERROR: mem limit not implemented"); -} - - - - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_post.c b/system/kernel/pdp_post.c deleted file mode 100644 index fb761d0..0000000 --- a/system/kernel/pdp_post.c +++ /dev/null @@ -1,48 +0,0 @@ - -/* - * Pure Data Packet system file. pdp logging. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include "pdp_post.h" - -/* list printing should be moved here too */ - -/* write a message to log (console) */ -void pdp_post_n(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} -void pdp_post(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - putc('\n', stderr); -} - - diff --git a/system/kernel/pdp_queue.c b/system/kernel/pdp_queue.c deleted file mode 100644 index 665a236..0000000 --- a/system/kernel/pdp_queue.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Pure Data Packet - processor queue module. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - - -/* - this is a the processor queue pdp system module - it receives tasks from objects that are schedules to - be computed in another thread. the object is signalled back - when the task is completed. - - this is not a standard pd class. it is a sigleton class - using a standard pd clock to poll for compleded methods on - every scheduler run. this is a hack to do thread synchronization - in a thread unsafe pd. - - the queue object can be reused. the pdp system however only - has one instance (one pdp queue. pdp remains a serial program.) - - */ - -#include "pdp.h" -#include <pthread.h> -#include <unistd.h> -#include <stdio.h> - - -#define D if (0) - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define PDP_QUEUE_LOGSIZE 10 -#define PDP_QUEUE_DELTIME 10.0f - - - - -/********************* general purpose pd process queue class *********************/ - -void pdp_procqueue_wait(t_pdp_procqueue *q) -{ - D post("pdp_procqueue_wait(%x): waiting for pdp_queue_thread to finish processing", q); - pthread_mutex_lock(&q->mut); - while(((q->curr - q->head) & q->mask) != 0){ - - pthread_cond_wait(&q->cond_processingdone, &q->mut); - } - pthread_mutex_unlock(&q->mut); - D post("pdp_procqueue_wait(%x): pdp_procqueue_thread has finished processing", q); - -} -void pdp_procqueue_finish(t_pdp_procqueue *q, int index) -{ - - if (-1 == index) { - //post("pdp_pq_remove: index == -1"); - return; - } - /* wait for processing thread to finish*/ - pdp_procqueue_wait(q); - - /* invalidate callback at index */ - q->q[index & q->mask].x_callback = 0; - q->q[index & q->mask].x_queue_id = 0; - -} - -static void pdp_procqueue_signal_processor(t_pdp_procqueue *q) -{ - - //NOTE: uncommenting these post statements causes a libc crash - //in mutex lock in putc - //D post("pdp_procqueue_signal_processor(%x): signalling process thread", q); - pthread_mutex_lock(&q->mut); - pthread_cond_signal(&q->cond_dataready); - pthread_mutex_unlock(&q->mut); - //D post("pdp_procqueue_signal_processor(%x): signalling done", q); - - -} - -static void pdp_procqueue_wait_for_feeder(t_pdp_procqueue *q) -{ - - - /* only use locking when there is no data */ - if(((q->curr - q->head) & q->mask) == 0){ - - /* signal processing done */ - D post("pdp_procqueue_wait_for_feeder(%x): signalling processing is done", q); - pthread_mutex_lock(&q->mut); - pthread_cond_signal(&q->cond_processingdone); - - /* wait until there is an item in the queue */ - while(((q->curr - q->head) & q->mask) == 0){ - pthread_cond_wait(&q->cond_dataready, &q->mut); - } - - pthread_mutex_unlock(&q->mut); - D post("pdp_procqueue_wait_for_feeder(%x): waiting done", q); - - } -} - -void pdp_procqueue_add(t_pdp_procqueue *q, void *owner, void *process, void *callback, int *queue_id) -{ - int i; - - /* if processing is in not in thread, just call the funcs */ - if (!q->use_thread){ - D post("pdp_procqueue_add(%q): calling processing routine directly", q); - if (queue_id) *queue_id = -1; - if (process) ((t_pdpmethod) process)(owner); - if (callback) ((t_pdpmethod) callback)(owner); - return; - } - - - /* if queue is full, call directly */ - if (1 == ((q->tail - q->head) & q->mask)) { - //post("pdp_procqueue_add: WARNING: processing queue (%x) is full.\n", q); - //post("pdp_procqueue_add: WARNING: tail %x, head %x, mask %x.\n", q->tail, q->head, q->mask); - //post("pdp_procqueue_add: WARNING: skipping process method, calling callback directly.\n"); - if (queue_id) *queue_id = -1; - if (callback) ((t_pdpmethod) callback)(owner); - return; - //exit(1); - } - - /* schedule method in thread queue */ - i = q->head & q->mask; - q->q[i].x_owner = owner; - q->q[i].x_process = process; - q->q[i].x_callback = callback; - q->q[i].x_queue_id = queue_id; - if (queue_id) *queue_id = i; - //post("pdp_queue_add: added method to queue, index %d", i); - - - // increase the packet count - q->packets++; - - // move head forward - q->head++; - - pdp_procqueue_signal_processor(q); - -} - - -/* processing thread */ -static void *pdp_procqueue_thread(void *vq) -{ - t_pdp_procqueue *q = (t_pdp_procqueue *)vq; - - D post("pdp_procqueue_thread(%x): thread started", q); - - while(1){ - t_process_queue_item *p; - - - D post("pdp_procqueue_thread(%x): waiting for feeder", q); - - /* wait until there is data available */ - pdp_procqueue_wait_for_feeder(q); - - - D post("pdp_procqueue_thread(%x): processing %d", q, q->curr & q->mask); - - - /* call the process routine */ - p = &q->q[q->curr & q->mask]; - if (p->x_process) - (p->x_process)(p->x_owner); - - /* advance */ - q->curr++; - - - } -} - - -/* call back all the callbacks */ -static void pdp_procqueue_callback (t_pdp_procqueue *q) -{ - - /* call callbacks for finished packets */ - while(0 != ((q->curr - q->tail) & q->mask)) - { - int i = q->tail & q->mask; - /* invalidate queue id */ - if(q->q[i].x_queue_id) *q->q[i].x_queue_id = -1; - /* call callback */ - if(q->q[i].x_callback) (q->q[i].x_callback)(q->q[i].x_owner); - //else post("pdp_pq_tick: callback %d is disabled",i ); - q->tail++; - } - -} - -/* the clock method */ -static void pdp_procqueue_tick (t_pdp_procqueue *q) -{ - /* do work */ - //if (!(ticks % 1000)) post("pdp tick %d", ticks); - - if (!q->use_thread) return; - - /* call callbacks */ - pdp_procqueue_callback(q); - - /* increase counter */ - q->ticks++; - - /* set clock for next update */ - clock_delay(q->pdp_clock, q->deltime); -} - - - -void pdp_procqueue_use_thread(t_pdp_procqueue* q, int t) -{ - /* if thread usage is being disabled, - wait for thread to finish processing first */ - if (t == 0) { - pdp_procqueue_wait(q); - q->use_thread = 0; - pdp_procqueue_callback(q); - clock_unset(q->pdp_clock); - } - else { - clock_unset(q->pdp_clock); - clock_delay(q->pdp_clock, q->deltime); - q->use_thread = 1; - } - -} - -void pdp_procqueue_init(t_pdp_procqueue *q, double milliseconds, int logsize) -{ - pthread_attr_t attr; - int size = 1 << logsize; - - /* setup pdp queue processor object */ - q->ticks = 0; - q->deltime = milliseconds; - - /* setup queue data */ - q->mask = size - 1; - q->head = 0; - q->tail = 0; - q->curr = 0; - q->q = pdp_alloc(size * sizeof(t_process_queue_item)); - memset(q->q, 0, size * sizeof(t_process_queue_item)); - - /* enable threads */ - q->use_thread = 1; - - /* setup synchro stuff */ - pthread_mutex_init(&q->mut, NULL); - pthread_cond_init(&q->cond_dataready, NULL); - pthread_cond_init(&q->cond_processingdone, NULL); - - - /* allocate the clock */ - q->pdp_clock = clock_new(q, (t_method)pdp_procqueue_tick); - - /* set the clock */ - clock_delay(q->pdp_clock, 0); - - /* start processing thread */ - - /* glibc doc says SCHED_OTHER is default, - but it seems not to be when initiated from a RT thread - so we explicitly set it here */ - pthread_attr_init (&attr); - //pthread_attr_setschedpolicy(&attr, SCHED_FIFO); - pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - - D post("pdp_procqueue_init(%x): starting thread", q); - pthread_create(&q->thread_id, &attr, pdp_procqueue_thread, (void *)q); - D post("pdp_procqueue_init(%x): back in pd thread", q); - - /* wait for processing thread to finish */ - //pdp_procqueue_wait(q); - - /* set default disable/enable thread here */ - //post("pdp_queue: THREAD PROCESSING ON BY DEFAULT!!"); - pdp_procqueue_use_thread(q,0); - -} - - - - -/* the (static) pdp queue object */ -static t_pdp_procqueue pdp_queue; - - -/* get the default queue */ -t_pdp_procqueue *pdp_queue_get_queue(void){return &pdp_queue;} - - -#if 1 -/* default pdp queue shortcut methods */ -void pdp_queue_wait() {pdp_procqueue_wait(&pdp_queue);} -void pdp_queue_finish(int index) { pdp_procqueue_finish(&pdp_queue, index);} -void pdp_queue_add(void *owner, void *process, void *callback, int *queue_id) { - pdp_procqueue_add(&pdp_queue, owner, process, callback, queue_id); -} -void pdp_queue_use_thread(int t) {pdp_procqueue_use_thread(&pdp_queue, t);} -void pdp_queue_setup(void){ - pdp_procqueue_init(&pdp_queue, PDP_QUEUE_DELTIME, PDP_QUEUE_LOGSIZE); - pdp_procqueue_use_thread(&pdp_queue,0); -} -#endif - - - - - - - -#ifdef __cplusplus -} -#endif diff --git a/system/kernel/pdp_symbol.c b/system/kernel/pdp_symbol.c deleted file mode 100644 index 32e9e33..0000000 --- a/system/kernel/pdp_symbol.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Pure Data Packet system implementation. : code implementing pdp's namespace (symbols) - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <string.h> -#include <pthread.h> -#include "pdp_symbol.h" -#include "pdp_list.h" -#include "pdp_debug.h" - -// some extra prototypes -void *pdp_alloc(int size); -void pdp_dealloc(void *data); - -// the symbol hash mutex -static pthread_mutex_t pdp_hash_mutex; - -#define HASHSIZE 1024 -static t_pdp_symbol *pdp_symhash[HASHSIZE]; - - -#define LOCK pthread_mutex_lock(&pdp_hash_mutex) -#define UNLOCK pthread_mutex_unlock(&pdp_hash_mutex) - - -static void _pdp_symbol_init(t_pdp_symbol *s) -{ - memset(s, 0, sizeof(*s)); - s->s_forth.t = a_undef; -} - - -/* shamelessly copied from pd src and made thread safe */ -t_pdp_symbol *_pdp_dogensym(char *s, t_pdp_symbol *oldsym) -{ - t_pdp_symbol **sym1, *sym2; - unsigned int hash1 = 0, hash2 = 0; - int length = 0; - char *s2 = s; - while (*s2) - { - hash1 += *s2; - hash2 += hash1; - length++; - s2++; - } - sym1 = pdp_symhash + (hash2 & (HASHSIZE-1)); - - /* lock hash */ - LOCK; - - while (sym2 = *sym1) - { - if (!strcmp(sym2->s_name, s)) goto gotit; - sym1 = &sym2->s_next; - } - if (oldsym){ - sym2 = oldsym; - } - else - { - sym2 = (t_pdp_symbol *)pdp_alloc(sizeof(*sym2)); - _pdp_symbol_init(sym2); - sym2->s_name = pdp_alloc(length+1); - sym2->s_next = 0; - strcpy(sym2->s_name, s); - } - *sym1 = sym2; - - gotit: - - /* unlock hash */ - UNLOCK; - return (sym2); -} - -t_pdp_symbol *pdp_gensym(char *s) -{ - return(_pdp_dogensym(s, 0)); -} - - -/* connect a parsed typelist to a symbol type name - 1 = succes, 0 = error (symbol already connected) */ -int pdp_symbol_set_typelist(t_pdp_symbol *s, t_pdp_list *typelist) -{ - int status = 0; - LOCK; - if (!s->s_type){ - s->s_type = typelist; - status = 1; - } - UNLOCK; - return status; -} - - -void pdp_symbol_apply_all(t_pdp_symbol_iterator it) -{ - int i; - for (i=0; i<HASHSIZE; i++){ - t_pdp_symbol *s; - for (s = pdp_symhash[i]; s; s=s->s_next){ - it(s); - } - - } -} - -t_pdp_symbol _pdp_sym_wildcard; -t_pdp_symbol _pdp_sym_float; -t_pdp_symbol _pdp_sym_int; -t_pdp_symbol _pdp_sym_symbol; -t_pdp_symbol _pdp_sym_packet; -t_pdp_symbol _pdp_sym_pointer; -t_pdp_symbol _pdp_sym_invalid; -t_pdp_symbol _pdp_sym_list; -t_pdp_symbol _pdp_sym_question_mark; -t_pdp_symbol _pdp_sym_atom; -t_pdp_symbol _pdp_sym_null; -t_pdp_symbol _pdp_sym_quote_start; -t_pdp_symbol _pdp_sym_quote_end; -t_pdp_symbol _pdp_sym_return; -t_pdp_symbol _pdp_sym_nreturn; -t_pdp_symbol _pdp_sym_defstart; -t_pdp_symbol _pdp_sym_defend; -t_pdp_symbol _pdp_sym_if; -t_pdp_symbol _pdp_sym_then; -t_pdp_symbol _pdp_sym_local; -t_pdp_symbol _pdp_sym_forth; -t_pdp_symbol _pdp_sym_call; -t_pdp_symbol _pdp_sym_push; -t_pdp_symbol _pdp_sym_pop; - -static void _sym(char *name, t_pdp_symbol *s) -{ - t_pdp_symbol *realsym; - _pdp_symbol_init(s); - s->s_name = name; - realsym = _pdp_dogensym(name, s); - PDP_ASSERT(realsym == s); // if this fails, the symbol was already defined -} - -void pdp_symbol_setup(void) -{ - // create mutexes - pthread_mutex_init(&pdp_hash_mutex, NULL); - - // init symbol hash - memset(pdp_symhash, 0, HASHSIZE * sizeof(t_pdp_symbol *)); - - // setup predefined symbols (those that have direct pointer access for speedup) - _sym("*", &_pdp_sym_wildcard); - _sym("float", &_pdp_sym_float); - _sym("int", &_pdp_sym_int); - _sym("symbol", &_pdp_sym_symbol); - _sym("packet", &_pdp_sym_packet); - _sym("pointer", &_pdp_sym_pointer); - _sym("invalid", &_pdp_sym_invalid); - _sym("list", &_pdp_sym_list); - _sym("?", &_pdp_sym_question_mark); - _sym("atom", &_pdp_sym_atom); - _sym("null", &_pdp_sym_null); - _sym("[", &_pdp_sym_quote_start); - _sym("]", &_pdp_sym_quote_end); - _sym("ret", &_pdp_sym_return); - _sym("nret", &_pdp_sym_nreturn); - _sym(":", &_pdp_sym_defstart); - _sym(";", &_pdp_sym_defend); - _sym("if", &_pdp_sym_if); - _sym("then", &_pdp_sym_then); - _sym("local", &_pdp_sym_local); - _sym("forth", &_pdp_sym_forth); - _sym("call", &_pdp_sym_call); - _sym("push", &_pdp_sym_push); - _sym("pop", &_pdp_sym_pop); - -} - - diff --git a/system/kernel/pdp_type.c b/system/kernel/pdp_type.c deleted file mode 100644 index c220269..0000000 --- a/system/kernel/pdp_type.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Pure Data Packet system implementation. : code for handling different packet types - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* this file contains type handling routines */ - -#include <stdarg.h> -#include <string.h> -#include <pthread.h> -#include "pdp.h" - - -// debug -#define D if (0) - - -static t_pdp_list *conversion_list; - -#define INIT_MAX_CACHE_SIZE 32 - -static t_pdp_list *cached_conversion_list; -static int max_cache_size; - -/* mutex */ -static pthread_mutex_t pdp_hash_mutex; -static pthread_mutex_t pdp_conversion_mutex; -static pthread_mutex_t pdp_cache_mutex; - -#define HASHSIZE 1024 -static t_pdp_symbol *pdp_symhash[HASHSIZE]; - - -/* shamelessly copied from pd src and made thread safe */ -t_pdp_symbol *_pdp_dogensym(char *s, t_pdp_symbol *oldsym) -{ - t_pdp_symbol **sym1, *sym2; - unsigned int hash1 = 0, hash2 = 0; - int length = 0; - char *s2 = s; - while (*s2) - { - hash1 += *s2; - hash2 += hash1; - length++; - s2++; - } - sym1 = pdp_symhash + (hash2 & (HASHSIZE-1)); - - /* lock hash */ - pthread_mutex_lock(&pdp_hash_mutex); - - while (sym2 = *sym1) - { - if (!strcmp(sym2->s_name, s)) goto gotit; - sym1 = &sym2->s_next; - } - if (oldsym) sym2 = oldsym; - else - { - sym2 = (t_pdp_symbol *)pdp_alloc(sizeof(*sym2)); - sym2->s_name = pdp_alloc(length+1); - _pdp_symbol_clear_namespaces(sym2); - sym2->s_next = 0; - strcpy(sym2->s_name, s); - } - *sym1 = sym2; - - gotit: - - /* unlock hash */ - pthread_mutex_unlock(&pdp_hash_mutex); - return (sym2); -} - -t_pdp_symbol *pdp_gensym(char *s) -{ - return(_pdp_dogensym(s, 0)); -} - -/* convert a type to a list */ -t_pdp_list *pdp_type_to_list(t_pdp_symbol *type) -{ - char *c = type->s_name; - char *lastname = c; - char tmp[100]; - int n = 0; - t_pdp_list *l = pdp_list_new(0); - - while(*c){ - if (*c == '/'){ - strncpy(tmp, lastname, n); - tmp[n] = 0; - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(tmp)); - c++; - lastname = c; - n = 0; - } - else{ - c++; - n++; - } - } - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(lastname)); - - return l; -} - - -/* get the description symbol. this includes some compat transition stuff with a warning */ -t_pdp_symbol *pdp_packet_get_description(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - - if (!header) return pdp_gensym("invalid"); - else if (!header->desc){ - - post("ERROR: pdp_packet_get_description: packet %d has no description.", packet); - pdp_packet_print_debug(packet); - return pdp_gensym("unknown"); - } - else return header->desc; -} - - - -/* this runs a conversion program */ -int _pdp_type_run_conversion_program(t_pdp_conversion_program *program, - int packet, t_pdp_symbol *dest_template) -{ - /* run a conversion program: - treat the source packet as readonly, and cleanup intermediates, such - that the net result is the production of a new packet, with the - source packet intact. */ - - int p, tmp; - t_pdp_atom *a; - t_pdp_conversion_method m; - - // run the first line of the program - a = program->first; - m = a->w.w_pointer; - D post("DEBUG: _pdp_type_run_conversion_program: method = %x", m); - p = m(packet, dest_template); - D post("DEBUG: _pdp_type_run_conversion_program: packet returned = %d, type = %s", p, pdp_packet_get_description(p)->s_name); - - // run the remaining lines + cleanup intermediates - for (a=a->next; a; a=a->next){ - m = a->w.w_pointer; - D post("DEBUG: _pdp_type_run_conversion_program: next method ptr = %x", m); - tmp = m(p, dest_template); - pdp_packet_mark_unused(p); - p = tmp; - } - return p; -} - - -/* find a conversion program */ -t_pdp_conversion_program * -_pdp_type_find_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c; - t_pdp_atom *a; - t_pdp_conversion_program *retval = 0; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - for (a = conversion_list->first; a; a=a->next){ - c = a->w.w_pointer; - /* can be a wildcard match */ - if (pdp_type_description_match(src_pattern, c->src_pattern) && - pdp_type_description_match(dst_pattern, c->dst_pattern)) { - /* found a program */ - D post("DEBUG: _pdp_type_find_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - goto gotit; - } - } - - /* no conversion program was found */ - retval = 0; - gotit: - - /* lock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - return retval; -} - -/* find a cached conversion program - if one is found it will be moved to the back of the queue (MRU) */ -t_pdp_conversion_program * -_pdp_type_find_cached_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c, *c_tmp; - t_pdp_atom *a; - t_pdp_conversion_program *retval = 0; - - /* lock cached list */ - pthread_mutex_lock(&pdp_cache_mutex); - - for (a = cached_conversion_list->first; a; a=a->next){ - c = a->w.w_pointer; - /* must be exact match */ - if ((src_pattern == c->src_pattern) && - (dst_pattern == c->dst_pattern)) { - - /* found a program */ - D post("DEBUG: _pdp_type_find_cached_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - - /* make MRU (move to back) */ - c_tmp = cached_conversion_list->last->w.w_pointer; - cached_conversion_list->last->w.w_pointer = c; - a->w.w_pointer = c_tmp; - goto gotit; - } - } - - retval = 0; - - gotit: - - - /* un lock cached list */ - pthread_mutex_unlock(&pdp_cache_mutex); - - /* no conversion program was found */ - return retval; -} - - -/* conversion program manipulations */ -void pdp_conversion_program_free(t_pdp_conversion_program *program) -{ - pdp_list_free(program); -} - -/* debug print */ -void _pdp_conversion_program_print(t_pdp_conversion_program *program) -{ - post("_pdp_conversion_program_print %x", program); - pdp_list_print(program); -} - -t_pdp_conversion_program *pdp_conversion_program_new(t_pdp_conversion_method method, ...) -{ - t_pdp_conversion_program *p = pdp_list_new(0); - t_pdp_conversion_method m = method; - va_list ap; - - D post("DEBUG: pdp_conversion_program_new:BEGIN"); - - pdp_list_add_back_pointer(p, m); - va_start(ap, method); - while (m = va_arg(ap, t_pdp_conversion_method)) pdp_list_add_back_pointer(p, m); - va_end(ap); - - D post("DEBUG: pdp_conversion_program_new:END"); - - return p; -} - -t_pdp_conversion_program *pdp_conversion_program_copy(t_pdp_conversion_program *program) -{ - if (program) return pdp_list_copy(program); - else return 0; -} - -void pdp_conversion_program_add(t_pdp_conversion_program *program, t_pdp_conversion_program *tail) -{ - return pdp_list_cat(program, tail); -} - -/* conversion registration */ -void pdp_type_register_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - t_pdp_conversion *c = (t_pdp_conversion *)pdp_alloc(sizeof(*c)); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - pdp_list_add_back_pointer(conversion_list, c); - - /* unlock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - -} - -/* register a cached conversion */ -void pdp_type_register_cached_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - - /* create the new conversion */ - t_pdp_conversion *c = (t_pdp_conversion *)pdp_alloc(sizeof(*c)); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - - /* lock cached conversion list */ - pthread_mutex_lock(&pdp_cache_mutex); - - /* check size, and remove LRU (top) if the cache is full */ - while (cached_conversion_list->elements >= max_cache_size){ - t_pdp_conversion *c_old = pdp_list_pop(cached_conversion_list).w_pointer; - if (c_old->program) pdp_conversion_program_free(c_old->program); - pdp_dealloc(c_old); - } - - /* add and make MRU (back) */ - pdp_list_add_back_pointer(cached_conversion_list, c); - - /* unlock cached conversion list */ - pthread_mutex_unlock(&pdp_cache_mutex); -} - -/* convert a given packet to a certain type (template) */ -int _pdp_packet_convert(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - t_pdp_symbol *tmp_type = 0; - int tmp_packet = -1; - - t_pdp_conversion_program *program = 0; - t_pdp_conversion_program *program_last = 0; - t_pdp_conversion_program *program_tail = 0; - - /* check if there is a program in the cached list, if so run it */ - if (program = _pdp_type_find_cached_conversion_program(type, dest_template)) - return _pdp_type_run_conversion_program(program, packet, dest_template); - - /* if it is not cached, iteratively convert - and save program on top of cache list if a conversion path (program) was found */ - - // run first conversion that matches - program = pdp_conversion_program_copy(_pdp_type_find_conversion_program(type, dest_template)); - program_last = program; - if (!program){ - D post("DEBUG: pdp_type_convert: (1) can't convert %s to %s", type->s_name, dest_template->s_name); - return -1; - } - tmp_packet = _pdp_type_run_conversion_program(program, packet, dest_template); - tmp_type = pdp_packet_get_description(tmp_packet); - - // run more conversions if necessary, deleting intermediate packets - while (!pdp_type_description_match(tmp_type, dest_template)){ - int new_packet; - program_tail = _pdp_type_find_conversion_program(tmp_type, dest_template); - if (!program_tail){ - D post("DEBUG: pdp_type_convert: (2) can't convert %s to %s", tmp_type->s_name, dest_template->s_name); - pdp_packet_mark_unused(tmp_packet); - pdp_conversion_program_free(program); - return -1; - } - if (program_last == program_tail){ - post("ERROR: pdp_packet_convert: conversion loop detected"); - } - program_last = program_tail; - - pdp_conversion_program_add(program, program_tail); - new_packet = _pdp_type_run_conversion_program(program_tail, tmp_packet, dest_template); - pdp_packet_mark_unused(tmp_packet); - tmp_packet = new_packet; - tmp_type = pdp_packet_get_description(tmp_packet); - } - - // save the conversion program - pdp_type_register_cached_conversion(type, dest_template, program); - - // return resulting packet - return tmp_packet; - -} - -/* convert or copy ro */ -int pdp_packet_convert_ro(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, return a ro copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_ro(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - -/* convert or copy rw */ -int pdp_packet_convert_rw(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, just return a rw copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_rw(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - - -static void _setup_type_cache(t_pdp_symbol *s) -{ - t_pdp_list *l = pdp_type_to_list(s); - pthread_mutex_lock(&pdp_hash_mutex); //lock to prevent re-entry - if (!s->s_type){ - s->s_type = l; - l = 0; - } - pthread_mutex_unlock(&pdp_hash_mutex); - if (l) pdp_list_free(l); -} - -/* check if a type description fits a template - this function is symmetric */ -int pdp_type_description_match(t_pdp_symbol *description, t_pdp_symbol *pattern) -{ - int retval = 0; - - t_pdp_atom *ad, *ap; - t_pdp_symbol *wildcard = pdp_gensym("*"); - - - if (!(pattern)) post("PANICA"); - if (!(description)) post("PANICB"); - - - /* same type -> match */ - if (description == pattern) {retval = 1; goto done;} - - /* use the description list stored in the symbol for comparison */ - if (!(description->s_type)) _setup_type_cache(description); - if (!(pattern->s_type)) _setup_type_cache(pattern); - - if (!(pattern->s_type)) post("PANIC1"); - if (!(description->s_type)) post("PANIC2"); - - /* check size */ - if (description->s_type->elements != pattern->s_type->elements){retval = 0; goto done;} - - /* compare symbols of type list */ - for(ad=description->s_type->first, ap=pattern->s_type->first; ad; ad=ad->next, ap=ap->next){ - if (ad->w.w_symbol == wildcard) continue; - if (ap->w.w_symbol == wildcard) continue; - if (ad->w.w_symbol != ap->w.w_symbol) {retval = 0; goto done;} /* difference and not a wildcard */ - } - - /* type templates match */ - retval = 1; - - done: - D post("DEBUG: testing match between %s and %s: %s", - description->s_name, pattern->s_name, retval ? "match" : "no match"); - return retval; - -} - - - - - -/* setup method */ -void pdp_type_setup(void) -{ - int i; - - // create mutexes - pthread_mutex_init(&pdp_hash_mutex, NULL); - pthread_mutex_init(&pdp_conversion_mutex, NULL); - pthread_mutex_init(&pdp_cache_mutex, NULL); - - // init symbol hash - memset(pdp_symhash, 0, HASHSIZE * sizeof(t_pdp_symbol *)); - - // create conversion lists - cached_conversion_list = pdp_list_new(0); - conversion_list = pdp_list_new(0); - max_cache_size = INIT_MAX_CACHE_SIZE; - - - - -} diff --git a/system/kernel/pdp_type.c_old b/system/kernel/pdp_type.c_old deleted file mode 100644 index 4e42d53..0000000 --- a/system/kernel/pdp_type.c_old +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Pure Data Packet system implementation. : code for handling different packet types - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* this file contains type handling routines - note: pd symbols are used for type identification - for porting to other hosts, i suggest reimplementing t_pdp_symbol */ - -// debug - -#include <fnmatch.h> -#include <stdarg.h> -#include <string.h> -#include <pthread.h> -#include "pdp.h" - -/* - - - -*/ - - -#define D if (0) - - -static t_pdp_conversion *conversion_list; - -#define CACHE_SIZE 32 -static t_pdp_conversion *cached_conversion_list_start; -static t_pdp_conversion cached_conversion_array[CACHE_SIZE]; - -/* mutex */ -static pthread_mutex_t pdp_hash_mutex; -static pthread_mutex_t pdp_conversion_mutex; -static pthread_mutex_t pdp_cache_mutex; - -#define HASHSIZE 1024 -static t_pdp_symbol *pdp_symhash[HASHSIZE]; - - -/* shamelessly copied from pd src and made thread safe */ -t_pdp_symbol *_pdp_dogensym(char *s, t_pdp_symbol *oldsym) -{ - t_pdp_symbol **sym1, *sym2; - unsigned int hash1 = 0, hash2 = 0; - int length = 0; - char *s2 = s; - while (*s2) - { - hash1 += *s2; - hash2 += hash1; - length++; - s2++; - } - sym1 = pdp_symhash + (hash2 & (HASHSIZE-1)); - - /* lock hash */ - pthread_mutex_lock(&pdp_hash_mutex); - - while (sym2 = *sym1) - { - if (!strcmp(sym2->s_name, s)) goto gotit; - sym1 = &sym2->s_next; - } - if (oldsym) sym2 = oldsym; - else - { - sym2 = (t_pdp_symbol *)pdp_alloc(sizeof(*sym2)); - sym2->s_name = pdp_alloc(length+1); - _pdp_symbol_clear_namespaces(sym2); - sym2->s_next = 0; - strcpy(sym2->s_name, s); - } - *sym1 = sym2; - - gotit: - - /* unlock hash */ - pthread_mutex_unlock(&pdp_hash_mutex); - return (sym2); -} - -t_pdp_symbol *pdp_gensym(char *s) -{ - return(_pdp_dogensym(s, 0)); -} - -/* convert a type to a list */ -t_pdp_list *pdp_type_to_list(t_pdp_symbol *type) -{ - char *c = type->s_name; - char *lastname = c; - char tmp[100]; - int n = 0; - t_pdp_list *l = pdp_list_new(0); - - while(*c){ - if (*c == '/'){ - strncpy(tmp, lastname, n); - tmp[n] = 0; - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(tmp)); - c++; - lastname = c; - n = 0; - } - else{ - c++; - n++; - } - } - pdp_list_add_back(l, a_symbol, (t_pdp_word)pdp_gensym(lastname)); - - return l; -} - - -/* get the description symbol. this includes some compat transition stuff with a warning */ -t_pdp_symbol *pdp_packet_get_description(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - - if (!header) return pdp_gensym("invalid"); - else if (!header->desc){ - /* if description is not defined, try to reconstruct it (for backwards compat) */ - if (header->type == PDP_IMAGE){ - post("FIXME: pdp_type_get_description: packet %d has no description. using workaround.", packet); - return pdp_packet_image_get_description(packet); - } - else - return pdp_gensym("unknown"); - } - else return header->desc; -} - - - -/* this runs a conversion program */ -int _pdp_type_run_conversion_program(t_pdp_conversion_program *program, - int packet, t_pdp_symbol *dest_template) -{ - /* run a conversion program: - treat the source packet as readonly, and cleanup intermediates, such - that the net result is the production of a new packet, with the - source packet intact. */ - - int p, tmp; - - D post("DEBUG: _pdp_type_run_conversion_program: program = %x", program); - - // run the first line of the program - D post("DEBUG: _pdp_type_run_conversion_program: method = %x", *program); - p = (*program->method)(packet, dest_template); - D post("DEBUG: _pdp_type_run_conversion_program: packet returned = %d, type = %s", p, pdp_packet_get_description(p)->s_name); - - // run the remaining lines + cleanup intermediates - for (program = program->next; program ; program = program->next){ - D post("DEBUG: _pdp_type_run_conversion_program: next method ptr = %x", *program->method); - tmp = (*program->method)(p, dest_template); - pdp_packet_mark_unused(p); - p = tmp; - } - return p; -} - - -/* find a conversion program */ -t_pdp_conversion_program * -_pdp_type_find_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c; - t_pdp_conversion_program *retval = 0; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - for (c = conversion_list; c; c=c->next){ - /* can be a wildcard match */ - if (pdp_type_description_match(src_pattern, c->src_pattern) && - pdp_type_description_match(dst_pattern, c->dst_pattern)) { - /* found a program */ - D post("DEBUG: _pdp_type_find_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - goto gotit; - } - } - - /* no conversion program was found */ - retval = 0; - gotit: - - /* lock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - return retval; -} - -/* find a cached conversion program */ -t_pdp_conversion_program * -_pdp_type_find_cached_conversion_program(t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern) -{ - t_pdp_conversion *c; - t_pdp_conversion_program *retval = 0; - - /* lock cached list */ - pthread_mutex_lock(&pdp_cache_mutex); - - for (c = cached_conversion_list_start; c; c=c->next){ - /* must be exact match */ - if ((src_pattern == c->src_pattern) && - (dst_pattern == c->dst_pattern)) { - /* found a program */ - D post("DEBUG: _pdp_type_find_cached_conversion_program: found: %s -> %s", c->src_pattern->s_name, c->dst_pattern->s_name); - retval = c->program; - goto gotit; - } - } - - retval = 0; - - gotit: - - /* un lock cached list */ - pthread_mutex_unlock(&pdp_cache_mutex); - - /* no conversion program was found */ - return retval; -} - - -/* conversion program manipulations */ -void pdp_conversion_program_free(t_pdp_conversion_program *program) -{ - t_pdp_conversion_program *p = 0; - while (program) { - p = program; - program = program->next; - pdp_dealloc (p); - } -} - -/* debug print */ -void _pdp_conversion_program_print(t_pdp_conversion_program *program) -{ - D post("DEBUG: conversion program: %x", program); - while(program){ - D post("DEBUG: method: %x", program->method); - program = program->next; - } -} - -t_pdp_conversion_program *pdp_conversion_program_new(t_pdp_conversion_method method, ...) -{ - t_pdp_conversion_program head; - t_pdp_conversion_program *p = &head; - t_pdp_conversion_method m = method; - va_list ap; - - D post("DEBUG: pdp_conversion_program_new:BEGIN"); - - p = p->next = (t_pdp_conversion_program *)pdp_alloc(sizeof(*p)); - p->method = m; - va_start(ap, method); - while (m = va_arg(ap, t_pdp_conversion_method)){ - p = p->next = (t_pdp_conversion_program *)pdp_alloc(sizeof(*p)); - p->method = m; - } - p->next = 0; // terminate list - va_end(ap); - - D post("DEBUG: pdp_conversion_program_new:END"); - D _pdp_conversion_program_print(head.next); - - return head.next; -} - -t_pdp_conversion_program *pdp_conversion_program_copy(t_pdp_conversion_program *program) -{ - t_pdp_conversion_program head; - t_pdp_conversion_program *p = &head; - - for(;program; program=program->next){ - p = p->next = (t_pdp_conversion_program *)pdp_alloc(sizeof(*p)); - p->method = program->method; - } - p->next = 0; - return head.next; -} - -void pdp_conversion_program_add(t_pdp_conversion_program *program, t_pdp_conversion_program *tail) -{ - t_pdp_conversion_program *p = program; - - //D post("DEBUG: pdp_conversion_program_add:BEGIN"); - - - while (p->next) p = p->next; - p->next = pdp_conversion_program_copy(tail); - - //D post("DEBUG: pdp_conversion_program_add:END"); - -} - -/* conversion registration */ -void pdp_type_register_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - t_pdp_conversion head; - t_pdp_conversion *c = &head; - - /* lock conversion list */ - pthread_mutex_lock(&pdp_conversion_mutex); - - head.next = conversion_list; - - while (c->next) c=c->next; // add a new one to the end - c = c->next = (t_pdp_conversion *)pdp_alloc(sizeof(*c)); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - c->next = 0; - - conversion_list = head.next; - - /* unlock conversion list */ - pthread_mutex_unlock(&pdp_conversion_mutex); - -} - -/* register a cached conversion */ -void pdp_type_register_cached_conversion (t_pdp_symbol *src_pattern, t_pdp_symbol *dst_pattern, t_pdp_conversion_program *program) -{ - - t_pdp_conversion *save, *c, *c2; - - /* unlock cahed conversion list */ - pthread_mutex_lock(&pdp_cache_mutex); - - c2 = save = cached_conversion_list_start; - while (c2->next->next) c2 = c2->next; - c = c2->next; - c2->next = 0; - if (c->program) pdp_conversion_program_free(c->program); - c->src_pattern = src_pattern; - c->dst_pattern = dst_pattern; - c->program = program; - c->next = save; - cached_conversion_list_start = c; - - /* unlock cached conversion list */ - pthread_mutex_unlock(&pdp_cache_mutex); -} - -/* convert a given packet to a certain type (template) */ -int _pdp_packet_convert(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - t_pdp_symbol *tmp_type = 0; - int tmp_packet = -1; - - t_pdp_conversion_program *program = 0; - t_pdp_conversion_program *program_last = 0; - t_pdp_conversion_program *program_tail = 0; - - /* check if there is a program in the cached list, if so run it */ - if (program = _pdp_type_find_cached_conversion_program(type, dest_template)) - return _pdp_type_run_conversion_program(program, packet, dest_template); - - /* if it is not cached, iteratively convert - and save program on top of cache list if a conversion path (program) was found */ - - // run first conversion that matches - program = pdp_conversion_program_copy(_pdp_type_find_conversion_program(type, dest_template)); - program_last = program; - if (!program){ - D post("DEBUG: pdp_type_convert: (1) can't convert %s to %s", type->s_name, dest_template->s_name); - return -1; - } - tmp_packet = _pdp_type_run_conversion_program(program, packet, dest_template); - tmp_type = pdp_packet_get_description(tmp_packet); - - // run more conversions if necessary, deleting intermediate packets - while (!pdp_type_description_match(tmp_type, dest_template)){ - int new_packet; - program_tail = _pdp_type_find_conversion_program(tmp_type, dest_template); - if (!program_tail){ - D post("DEBUG: pdp_type_convert: (2) can't convert %s to %s", tmp_type->s_name, dest_template->s_name); - pdp_packet_mark_unused(tmp_packet); - pdp_conversion_program_free(program); - return -1; - } - if (program_last == program_tail){ - post("ERROR: pdp_packet_convert: conversion loop detected"); - } - program_last = program_tail; - - pdp_conversion_program_add(program, program_tail); - new_packet = _pdp_type_run_conversion_program(program_tail, tmp_packet, dest_template); - pdp_packet_mark_unused(tmp_packet); - tmp_packet = new_packet; - tmp_type = pdp_packet_get_description(tmp_packet); - } - - // save the conversion program - pdp_type_register_cached_conversion(type, dest_template, program); - - // return resulting packet - return tmp_packet; - -} - -/* convert or copy ro */ -int pdp_packet_convert_ro(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, return a ro copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_ro(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - -/* convert or copy rw */ -int pdp_packet_convert_rw(int packet, t_pdp_symbol *dest_template) -{ - t_pdp_symbol *type = pdp_packet_get_description(packet); - - /* if it is compatible, just return a rw copy */ - if (pdp_type_description_match(type, dest_template)) return pdp_packet_copy_rw(packet); - - /* if not, convert to a new type */ - else return _pdp_packet_convert(packet, dest_template); -} - - -static void _setup_type_cache(t_pdp_symbol *s) -{ - t_pdp_list *l = pdp_type_to_list(s); - pthread_mutex_lock(&pdp_hash_mutex); //lock to prevent re-entry - if (!s->s_type){ - s->s_type = l; - l = 0; - } - pthread_mutex_unlock(&pdp_hash_mutex); - if (l) pdp_list_free(l); -} - -/* check if a type description fits a template - this function is symmetric */ -int pdp_type_description_match(t_pdp_symbol *description, t_pdp_symbol *pattern) -{ - - -#if 1 - t_pdp_atom *ad, *ap; - t_pdp_symbol *wildcard = pdp_gensym("*"); - - /* same type -> match */ - if (description == pattern) return 1; - - /* use the description list stored in the symbol for comparison */ - if (!(description->s_type)) _setup_type_cache(description); - if (!(pattern->s_type)) _setup_type_cache(pattern); - - /* check size */ - if (description->s_type->elements != pattern->s_type->elements) return 0; - - /* compare symbols of type list */ - for(ad=description->s_type->first, ap=pattern->s_type->first; ad; ad=ad->next, ap=ap->next){ - if (ad->w.w_symbol == wildcard) continue; - if (ap->w.w_symbol == wildcard) continue; - if (ad->w.w_symbol != ap->w.w_symbol) return 0; /* difference and not a wildcard */ - } - - /* type templates match */ - return 1; - - -#else - int retval = 0; - if (description == pattern) retval = 1; - //else retval = (!fnmatch(pattern->s_name, description->s_name, FNM_FILE_NAME)); - - //hack: make a symmetric match symmetric by calling fnmatch a second time with reversed attributes - else retval = ((!fnmatch(pattern->s_name, description->s_name, FNM_FILE_NAME)) - ||(!fnmatch(description->s_name, pattern->s_name, FNM_FILE_NAME))); - - - D post("DEBUG: testing match between %s and %s: %s", description->s_name, pattern->s_name, retval ? "match" : "no match"); - - return retval; -#endif -} - - - - - -/* setup method */ -void pdp_type_setup(void) -{ - int i; - - // create mutexes - pthread_mutex_init(&pdp_hash_mutex, NULL); - pthread_mutex_init(&pdp_conversion_mutex, NULL); - pthread_mutex_init(&pdp_cache_mutex, NULL); - - // init hash - memset(pdp_symhash, 0, HASHSIZE * sizeof(t_pdp_symbol *)); - - // init conversion lists - conversion_list = 0; - for(i=0; i<CACHE_SIZE; i++){ - t_pdp_conversion *c = cached_conversion_array + i; - c->src_pattern = 0; - c->dst_pattern = 0; - c->program = 0; - c->next = c + 1; - } - cached_conversion_list_start = cached_conversion_array; - cached_conversion_array[CACHE_SIZE-1].next = 0; - - - -} diff --git a/system/kernel/pdp_ut.c b/system/kernel/pdp_ut.c deleted file mode 100644 index dadc493..0000000 --- a/system/kernel/pdp_ut.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Pure Data Packet - Utility toolkit objects. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* This file contains some small utility pd objects that make working with - pdp objects a lot easier. Mainly as glue to be used in the abstractions - in the distro. */ - - -#include "pdp.h" -#include <math.h> - -/* this object does an add, scale, clip operation */ - -t_class *pdp_ut_addscaleclip_class; - -typedef struct pdp_ut_addscaleclip_struct -{ - t_object x_obj; - t_outlet *x_outlet0; - t_float x_min; - t_float x_max; - t_float x_offset; - t_float x_scale; -} t_pdp_ut_addscaleclip; - - -static void pdp_ut_addscaleclip_float(t_pdp_ut_addscaleclip *x, t_floatarg f) -{ - f += x->x_offset; - f *= x->x_scale; - f = (f < x->x_min) ? x->x_min : f; - f = (f > x->x_max) ? x->x_max : f; - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_addscaleclip_free(t_pdp_ut_addscaleclip *x){} - -void *pdp_ut_addscaleclip_new(t_floatarg offset, t_floatarg scale, t_floatarg min, t_floatarg max) -{ - t_pdp_ut_addscaleclip *x = (t_pdp_ut_addscaleclip *)pd_new(pdp_ut_addscaleclip_class); - x->x_outlet0 = outlet_new(&x->x_obj, &s_float); - x->x_offset = offset; - x->x_scale = scale; - x->x_min = min; - x->x_max = max; - return (void *)x; -} - -void pdp_ut_addscaleclip_setup(void) -{ - pdp_ut_addscaleclip_class = class_new(gensym("pdp_ut_addscaleclip"), (t_newmethod)pdp_ut_addscaleclip_new, - (t_method)pdp_ut_addscaleclip_free, sizeof(t_pdp_ut_addscaleclip), 0, - A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_addscaleclip_class, pdp_ut_addscaleclip_float); -} - - -/* pdp_ut_logmap does a logarithmic parameter mapping [0->1] x -> min(max/min)^x max an add, scale, clip operation */ -/* pdp_ut_logmap_comp does x -> min(max/min)^(1-x) */ -/* pdp_ut_linmap dos x -> min + (max - min * x */ - -t_class *pdp_ut_linmap_class; -t_class *pdp_ut_logmap_class; -t_class *pdp_ut_logmap_comp_class; - -typedef struct pdp_ut_map_struct -{ - t_object x_obj; - t_outlet *x_outlet0; - t_float x_min; - t_float x_max; -} t_pdp_ut_map; - - -static void pdp_ut_logmap_float(t_pdp_ut_map *x, t_floatarg f) -{ - f = (f < 0.0f) ? 0.0f : f; - f = (f > 1.0f) ? 1.0f : f; - - f = x->x_min * pow((x->x_max / x->x_min), f); - - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_linmap_float(t_pdp_ut_map *x, t_floatarg f) -{ - f = (f < 0.0f) ? 0.0f : f; - f = (f > 1.0f) ? 1.0f : f; - - f = x->x_min + ((x->x_max - x->x_min) * f); - - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_logmap_comp_float(t_pdp_ut_map *x, t_floatarg f) -{ - f = (f < 0.0f) ? 0.0f : f; - f = (f > 1.0f) ? 1.0f : f; - - f = x->x_min * pow((x->x_max / x->x_min), (1.0f - f)); - - outlet_float(x->x_outlet0, f); -} - -static void pdp_ut_map_free(t_pdp_ut_map *x){} - - -void pdp_ut_map_init(t_pdp_ut_map *x, t_floatarg min, t_floatarg max) -{ - x->x_outlet0 = outlet_new(&x->x_obj, &s_float); - x->x_min = min; - x->x_max = max; -} - -void *pdp_ut_logmap_new(t_floatarg min, t_floatarg max) -{ - t_pdp_ut_map *x = (t_pdp_ut_map *)pd_new(pdp_ut_logmap_class); - pdp_ut_map_init(x, min, max); - return (void *)x; -} - -void *pdp_ut_linmap_new(t_floatarg min, t_floatarg max) -{ - t_pdp_ut_map *x = (t_pdp_ut_map *)pd_new(pdp_ut_linmap_class); - pdp_ut_map_init(x, min, max); - return (void *)x; -} - -void *pdp_ut_logmap_comp_new(t_floatarg min, t_floatarg max) -{ - t_pdp_ut_map *x = (t_pdp_ut_map *)pd_new(pdp_ut_logmap_comp_class); - pdp_ut_map_init(x, min, max); - return (void *)x; -} - -void pdp_ut_logmap_setup(void) -{ - pdp_ut_logmap_class = class_new(gensym("pdp_ut_logmap"), (t_newmethod)pdp_ut_logmap_new, - (t_method)pdp_ut_map_free, sizeof(t_pdp_ut_map), 0, - A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_logmap_class, pdp_ut_logmap_float); -} - -void pdp_ut_logmap_comp_setup(void) -{ - pdp_ut_logmap_comp_class = class_new(gensym("pdp_ut_logmap_comp"), (t_newmethod)pdp_ut_logmap_comp_new, - (t_method)pdp_ut_map_free, sizeof(t_pdp_ut_map), 0, - A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_logmap_comp_class, pdp_ut_logmap_comp_float); -} - -void pdp_ut_linmap_setup(void) -{ - pdp_ut_linmap_class = class_new(gensym("pdp_ut_linmap"), (t_newmethod)pdp_ut_linmap_new, - (t_method)pdp_ut_map_free, sizeof(t_pdp_ut_map), 0, - A_FLOAT, A_FLOAT, A_NULL); - class_addfloat(pdp_ut_linmap_class, pdp_ut_linmap_float); -} - - - -t_class *pdp_ut_rgb2ycrcb_class; - -typedef struct pdp_ut_rgb2ycrcb -{ - t_object x_obj; - t_outlet *x_outlet_luma; - t_outlet *x_outlet_chroma_red; - t_outlet *x_outlet_chroma_blue; - - t_float x_red, x_green, x_blue; - -} t_pdp_ut_rgb2ycrcb; - - -static void pdp_ut_rgb2ycrcb_bang (t_pdp_ut_rgb2ycrcb* x) -{ - - float luma = 0.299f * x->x_red + 0.587f * x->x_green + 0.114f * x->x_blue; - float chroma_red = (x->x_red - luma) * 0.713f; - float chroma_blue = (x->x_blue - luma) * 0.565f; - - outlet_float(x->x_outlet_chroma_blue, chroma_blue); - outlet_float(x->x_outlet_chroma_red, chroma_red); - outlet_float(x->x_outlet_luma, luma); - -} - - -static void pdp_ut_rgb2ycrcb_red (t_pdp_ut_rgb2ycrcb* x, t_floatarg f) {x->x_red = f; pdp_ut_rgb2ycrcb_bang(x);} -static void pdp_ut_rgb2ycrcb_green (t_pdp_ut_rgb2ycrcb* x, t_floatarg f) {x->x_green = f; pdp_ut_rgb2ycrcb_bang(x);} -static void pdp_ut_rgb2ycrcb_blue (t_pdp_ut_rgb2ycrcb* x, t_floatarg f) {x->x_blue = f; pdp_ut_rgb2ycrcb_bang(x);} - - - -static void pdp_ut_rgb2ycrcb_free (t_pdp_ut_rgb2ycrcb* x) {} -static void* pdp_ut_rgb2ycrcb_new(void) -{ - t_pdp_ut_rgb2ycrcb *x = (t_pdp_ut_rgb2ycrcb *)pd_new(pdp_ut_rgb2ycrcb_class); - - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("green")); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("blue")); - - x->x_outlet_luma = outlet_new(&x->x_obj, &s_float); - x->x_outlet_chroma_red = outlet_new(&x->x_obj, &s_float); - x->x_outlet_chroma_blue = outlet_new(&x->x_obj, &s_float); - - x->x_red = 0.0f; - x->x_green = 0.0f; - x->x_blue = 0.0f; - - - return (void *)x; -} - -void pdp_ut_rgb2ycrcb_setup(void) -{ - pdp_ut_rgb2ycrcb_class = class_new(gensym("pdp_ut_rgb2ycrcb"), (t_newmethod)pdp_ut_rgb2ycrcb_new, - (t_method)pdp_ut_rgb2ycrcb_free, sizeof(t_pdp_ut_rgb2ycrcb), 0, A_NULL); - class_addfloat(pdp_ut_rgb2ycrcb_class, pdp_ut_rgb2ycrcb_red); - class_addmethod(pdp_ut_rgb2ycrcb_class, (t_method)pdp_ut_rgb2ycrcb_green, gensym("green"), A_FLOAT, A_NULL); - class_addmethod(pdp_ut_rgb2ycrcb_class, (t_method)pdp_ut_rgb2ycrcb_blue, gensym("blue"), A_FLOAT, A_NULL); -} - - -#ifdef __cplusplus -extern "C" -{ -#endif - -void pdp_ut_setup(void) -{ - pdp_ut_addscaleclip_setup(); - pdp_ut_logmap_setup(); - pdp_ut_logmap_comp_setup(); - pdp_ut_linmap_setup(); - pdp_ut_rgb2ycrcb_setup(); -} - - -#ifdef __cplusplus -} -#endif diff --git a/system/mmx/Makefile b/system/mmx/Makefile deleted file mode 100644 index 51e5052..0000000 --- a/system/mmx/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -include ../../Makefile.config - -OBJ = \ -pixel_pack_s16u8.o \ -pixel_unpack_u8s16.o \ -pixel_add_s16.o \ -pixel_mul_s16.o \ -pixel_mix_s16.o \ -pixel_randmix_s16.o \ -pixel_conv_hor_s16.o \ -pixel_conv_ver_s16.o \ -pixel_affine_s16.o \ -pixel_biquad_s16.o \ -pixel_ca_s1.o \ -pixel_rand_s16.o \ -pixel_crot_s16.o \ -pixel_gain_s16.o \ -pixel_resample_s16.o \ -pixel_cheby_s16.o - -all: $(OBJ) - -test: pdp_mmx_test.o $(OBJ) - gcc -o pdp_mmx_test pdp_mmx_test.o $(OBJ) -g - -clean: - rm -f *.o - rm -f *~ - rm -f pdp_mmx.a - rm -f pdp_mmx_test - - diff --git a/system/mmx/pdp_mmx_test.c b/system/mmx/pdp_mmx_test.c deleted file mode 100644 index e93539f..0000000 --- a/system/mmx/pdp_mmx_test.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "pdp_mmx.h" - -#define FP(x) ((short int)(((float)(x) * 2 * 256.0f))) - -#define nbp 256 - - short int a1[4] = {0x0100,0x0100,0x0100,0x0100}; - short int a2[4] = {0x0100,0x0100,0x0100,0x0100}; - short int b0[4] = {0x0100,0x0100,0x0100,0x0100}; - short int b1[4] = {0x0100,0x0100,0x0100,0x0100}; - short int b2[4] = {0x0100,0x0100,0x0100,0x0100}; - - short int u1[4] = {0x0100,0x0100,0x0100,0x0100}; - short int u2[4] = {0x0100,0x0100,0x0100,0x0100}; - - short int x0[4] = {0x0100,0x0100,0x0100,0x0100}; - short int x1[4] = {0x0100,0x0100,0x0100,0x0100}; - short int x2[4] = {0x0100,0x0100,0x0100,0x0100}; - short int x3[4] = {0x0100,0x0100,0x0100,0x0100}; - -void print_pixel(unsigned int i) -{ - if (i) printf("x "); - else printf(". "); -} - -void print_line(void) -{ - printf("\n"); -} - -void print_square(unsigned char *c) -{ - int i,j; - - for(j=7; j>=0; j--){ - for(i=0; i<8; i++) print_pixel(c[j] & (1<<(7-i))); - printf("\n"); - } - -} - -main() -{ - - unsigned char src[16]={1,2,3,4,5,6,7,8,-1,-2,-3,-4,-5,-6,-7,-8}; - unsigned char dst[8]; - - - print_square(src); - print_line(); - print_square(src+8); - print_line(); - - pixel_test_s1(dst,src,1,1); - - print_square(dst); - print_line(); - - - -} diff --git a/system/mmx/pixel_add_s16.s b/system/mmx/pixel_add_s16.s deleted file mode 100644 index 8d4c7df..0000000 --- a/system/mmx/pixel_add_s16.s +++ /dev/null @@ -1,55 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_add_s16 -.type pixel_add_s16,@function - -# simple add -# void pixel_add_s16(int *left, int *right, int nb_4pixel_vectors) - -pixel_add_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 8(%ebp), %edi # left array - movl 12(%ebp), %esi # right array - movl 16(%ebp), %ecx # pixel count - - - .align 16 - .loop_mix: - -# prefetch 128(%esi) - movq (%esi), %mm1 # load right 4 pixels from memory - movq (%edi), %mm0 # load 4 left pixels from memory - paddsw %mm1, %mm0 # mix - movq %mm0, (%edi) - addl $8, %esi - addl $8, %edi - decl %ecx - jnz .loop_mix # loop - - emms - - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_affine_s16.s b/system/mmx/pixel_affine_s16.s deleted file mode 100644 index b357de3..0000000 --- a/system/mmx/pixel_affine_s16.s +++ /dev/null @@ -1,59 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_affine_s16 -.type pixel_affine_s16,@function - -# void pixel_affine_s16(int *buf, int nb_8pixel_vectors, short int gain[4], short int offset[4]) - -pixel_affine_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 20(%ebp), %edi - movq (%edi), %mm6 # get offset vector - - movl 16(%ebp), %edi - movq (%edi), %mm7 # get gain vector - - movl 8(%ebp), %esi # input array - movl 12(%ebp), %ecx # pixel count - - - .align 16 - .loop_affine: - -# prefetch 128(%esi) - movq (%esi), %mm0 # load 4 pixels from memory - pmulhw %mm7, %mm0 # apply gain (s).15 fixed point - psllw $1, %mm0 # apply correction shift - paddsw %mm6, %mm0 # add offset - movq %mm0, (%esi) # store result in memory - - addl $8, %esi # increment source pointer - decl %ecx - jnz .loop_affine # loop - - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_biquad_dirI_s16.s b/system/mmx/pixel_biquad_dirI_s16.s deleted file mode 100644 index 1729502..0000000 --- a/system/mmx/pixel_biquad_dirI_s16.s +++ /dev/null @@ -1,361 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - - - # TODO MOVE TO DIRECT FORM II - # y[k] = b0 * x[k] + u1[k-1] - # u1[k] = b1 * x[k] + u2[k-1] - a1 * y[k] - # u2[k] = b2 * x[k] - a2 * y[k] - - # input in register: - # %mm0-mm3: input 4x4 pixels {x0 x1 x2 x3} - # %esi: coef memory (a1, a2, b0, b1, b2) - # %edi: state memory (u1, u2) - - - # return in register: - # %mm0-mm4: 4x4 pixels result - - - .biquad_4x4_pixels: - .align 16 - # prescale - movq -8(%esi), %mm4 - pmulhw %mm4, %mm0 - pmulhw %mm4, %mm1 - pmulhw %mm4, %mm2 - pmulhw %mm4, %mm3 - psllw $1, %mm0 - psllw $1, %mm1 - psllw $1, %mm2 - psllw $1, %mm3 - - - # first vector - movq 0(%edi), %mm4 # mm4 <- u[-1] - movq 8(%edi), %mm5 # mm5 <- u[-2] - movq %mm4, %mm6 - movq %mm5, %mm7 - - pmulhw 0(%esi), %mm6 # multiply by a1 - pmulhw 8(%esi), %mm7 # multiply by a2 - - paddsw %mm6, %mm0 # accumulate - paddsw %mm7, %mm0 # accumulate - paddsw %mm0, %mm0 # scale by 2 (since all fixed point muls are x*y/2) - - movq %mm0, %mm6 # mm6 <- u[0] - movq %mm4, %mm7 # mm7 <- u[-1] - pmulhw 16(%esi), %mm0 # multiply by b0 - pmulhw 24(%esi), %mm4 # multiply by b1 - pmulhw 32(%esi), %mm5 # multiply by b2 - - paddsw %mm4, %mm0 # accumulate - paddsw %mm5, %mm0 # accumulate - - # mm0 is result 0 - - # second vector - movq %mm6, %mm4 # mm4 <- u[0] - movq %mm7, %mm5 # mm5 <- u[-1] - - pmulhw 0(%esi), %mm6 # multiply by a1 - pmulhw 8(%esi), %mm7 # multiply by a2 - - paddsw %mm6, %mm1 # accumulate - paddsw %mm7, %mm1 # accumulate - paddsw %mm1, %mm1 # scale by 2 - - - movq %mm1, %mm6 # mm6 <- u[1] - movq %mm4, %mm7 # mm7 <- u[0] - pmulhw 16(%esi), %mm1 # multiply by b0 - pmulhw 24(%esi), %mm4 # multiply by b1 - pmulhw 32(%esi), %mm5 # multiply by b2 - - paddsw %mm4, %mm1 # accumulate - paddsw %mm5, %mm1 # accumulate - - # mm1 is result 1 - - # third vector - movq %mm6, %mm4 # mm4 <- u[1] - movq %mm7, %mm5 # mm5 <- u[0] - - pmulhw 0(%esi), %mm6 # multiply by a1 - pmulhw 8(%esi), %mm7 # multiply by a2 - - paddsw %mm6, %mm2 # accumulate - paddsw %mm7, %mm2 # accumulate - paddsw %mm2, %mm2 # scale by 2 - - - movq %mm2, %mm6 # mm6 <- u[2] - movq %mm4, %mm7 # mm7 <- u[1] - pmulhw 16(%esi), %mm2 # multiply by b0 - pmulhw 24(%esi), %mm4 # multiply by b1 - pmulhw 32(%esi), %mm5 # multiply by b2 - - paddsw %mm4, %mm2 # accumulate - paddsw %mm5, %mm2 # accumulate - - # mm2 is result 2 - - # fourth vector - movq %mm6, %mm4 # mm4 <- u[2] - movq %mm7, %mm5 # mm5 <- u[1] - - pmulhw 0(%esi), %mm6 # multiply by a1 - pmulhw 8(%esi), %mm7 # multiply by a2 - - paddsw %mm6, %mm3 # accumulate - paddsw %mm7, %mm3 # accumulate - paddsw %mm3, %mm3 # scale by 2 - - - movq %mm3, 0(%edi) # store u[3] - movq %mm4, 8(%edi) # store u[2] - pmulhw 16(%esi), %mm3 # multiply by b0 - pmulhw 24(%esi), %mm4 # multiply by b1 - pmulhw 32(%esi), %mm5 # multiply by b2 - - paddsw %mm4, %mm3 # accumulate - paddsw %mm5, %mm3 # accumulate - - # mm3 is result 3 - - ret - - - # in order to use the 4 line parallel biquad routine on horizontal - # lines, we need to reorder (rotate or transpose) the matrix, since - # images are scanline encoded, and we want to work in parallell - # on 4 lines. - # - # since the 4 lines are independent, it doesnt matter in which order - # the the vector elements are present. - # - # this allows us to use the same routine for left->right and right->left - # processing. - # - # some comments on the non-abelean group of square isometries consisting of - # (I) identity - # (H) horizontal axis mirror - # (V) vertical axis mirror - # (T) transpose (diagonal axis mirror) - # (A) antitranspose (antidiagonal axis mirror) - # (R1) 90deg anticlockwize rotation - # (R2) 180deg rotation - # (R3) 90deg clockwize rotation - # - # - # we basicly have two options: (R1,R3) or (T,A) - # we opt for T and A because they are self inverting, which improves locality - # - # use antitranspose for right to left an transpose - # for left to right (little endian) - - - # antitranspose 4x4 - - # input - # %mm3 == {d0 d1 d2 d3} - # %mm2 == {c0 c1 c2 c3} - # %mm1 == {b0 b1 b2 b3} - # %mm0 == {a0 a1 a2 a3} - - # output - # %mm3 == {a3 b3 c3 d3} - # %mm2 == {a2 b2 c2 d2} - # %mm1 == {a1 b1 c1 d1} - # %mm0 == {a0 b0 c0 d0} - - - .antitranspose_4x4: - .align 16 - movq %mm3, %mm4 - punpcklwd %mm1, %mm4 # mm4 <- {b2 d2 b3 d3} - movq %mm3, %mm5 - punpckhwd %mm1, %mm5 # mm5 <- {b0 d0 b1 d1} - - movq %mm2, %mm6 - punpcklwd %mm0, %mm6 # mm6 <- {a2 c2 a3 c3} - movq %mm2, %mm7 - punpckhwd %mm0, %mm7 # mm7 <- {a0 c0 a1 c1} - - movq %mm4, %mm3 - punpcklwd %mm6, %mm3 # mm3 <- {a3 b3 c3 d3} - movq %mm4, %mm2 - punpckhwd %mm6, %mm2 # mm2 <- {a2 b2 c2 d2} - - movq %mm5, %mm1 - punpcklwd %mm7, %mm1 # mm1 <- {a1 b1 c1 d1} - movq %mm5, %mm0 - punpckhwd %mm7, %mm0 # mm0 <- {a0 b0 c0 d0} - - ret - - - - # transpose 4x4 - - # input - # %mm3 == {d3 d2 d1 d0} - # %mm2 == {c3 c2 c1 c0} - # %mm1 == {b3 b2 b1 b0} - # %mm0 == {a3 a2 a1 a0} - - # output - # %mm3 == {d3 c3 b3 a3} - # %mm2 == {d2 c2 b2 a2} - # %mm1 == {d1 c1 b1 a1} - # %mm0 == {d0 c0 b0 a0} - - - .transpose_4x4: - .align 16 - movq %mm0, %mm4 - punpcklwd %mm2, %mm4 # mm4 <- {c1 a1 c0 a0} - movq %mm0, %mm5 - punpckhwd %mm2, %mm5 # mm5 <- {c3 a3 c2 a2} - - movq %mm1, %mm6 - punpcklwd %mm3, %mm6 # mm6 <- {d1 b1 d0 b0} - movq %mm1, %mm7 - punpckhwd %mm3, %mm7 # mm7 <- {d3 b3 d2 b2} - - movq %mm4, %mm0 - punpcklwd %mm6, %mm0 # mm0 <- {d0 c0 b0 a0} - movq %mm4, %mm1 - punpckhwd %mm6, %mm1 # mm1 <- {d1 c1 b1 a1} - - movq %mm5, %mm2 - punpcklwd %mm7, %mm2 # mm2 <- {d2 c2 b2 a2} - movq %mm5, %mm3 - punpckhwd %mm7, %mm3 # mm3 <- {d3 c3 b3 a3} - - ret - - -.globl pixel_biquad_vertb_s16 -.type pixel_biquad_vertb_s16,@function - - -# pixel_biquad_vertbr_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - - -pixel_biquad_vertb_s16: - - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %edx # line with - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - movl %edx, %eax - shll $1, %eax - addl %edx, %eax # eax = 3 * edx - - .align 16 - .biquad_vertb_line_loop: - movq (%ebx), %mm0 - movq (%ebx,%edx,1), %mm1 - movq (%ebx,%edx,2), %mm2 - movq (%ebx,%eax,1), %mm3 - call .biquad_4x4_pixels - movq %mm0, (%ebx) - movq %mm1, (%ebx,%edx,1) - movq %mm2, (%ebx,%edx,2) - movq %mm3, (%ebx,%eax,1) - addl %edx, %ebx - addl %eax, %ebx - decl %ecx - jnz .biquad_vertb_line_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - -.globl pixel_biquad_horlr_s16 -.type pixel_biquad_horlr_s16,@function - - -# pixel_biquad_hor_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - - -pixel_biquad_horlr_s16: - - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %edx # line with - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - movl %edx, %eax - shll $1, %eax - addl %edx, %eax # eax = 3 * edx - - .align 16 - .biquad_horlr_line_loop: - movq (%ebx), %mm0 - movq (%ebx,%edx,1), %mm1 - movq (%ebx,%edx,2), %mm2 - movq (%ebx,%eax,1), %mm3 - call .transpose_4x4 - call .biquad_4x4_pixels - call .transpose_4x4 - movq %mm0, (%ebx) - movq %mm1, (%ebx,%edx,1) - movq %mm2, (%ebx,%edx,2) - movq %mm3, (%ebx,%eax,1) - addl $8, %ebx - decl %ecx - jnz .biquad_horlr_line_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - - - diff --git a/system/mmx/pixel_biquad_s16.s b/system/mmx/pixel_biquad_s16.s deleted file mode 100644 index 844b041..0000000 --- a/system/mmx/pixel_biquad_s16.s +++ /dev/null @@ -1,451 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - - - # DIRECT FORM II BIQUAD - # - # y[k] = b0 * x[k] + u1[k-1] - # u1[k] = b1 * x[k] + u2[k-1] - a1 * y[k] - # u2[k] = b2 * x[k] - a2 * y[k] - # MACRO: df2 <reg> - # - # computes a direct form 2 biquad - # does not use {mm0-mm3}\<inreg> - # - # input: <reg> == input - # %mm4 == state 1 - # %mm5 == state 2 - # (%esi) == biquad coefs (-a1 -a2 b0 b1 b2) in s1.14 - # output: <reg> == output - # %mm4 == state 1 - # %mm5 == state 2 - - .macro df2 reg - movq \reg, %mm6 # mm6 == x[k] - movq \reg, %mm7 # mm7 == x[k] - pmulhw 16(%esi), %mm6 # mm6 == x[k] * b0 - pmulhw 24(%esi), %mm7 # mm7 == x[k] * b1 - paddw %mm4, %mm6 # mm6 == x[k] * b0 + u1[k-1] == y[k] - paddw %mm5, %mm7 # mm7 == x[k] * b1 + u2[k-1] - paddsw %mm6, %mm6 # compensate for mul = x*y/4 (coefs are s1.14 fixed point) - paddsw %mm6, %mm6 # paddsw ensures saturation - movq \reg, %mm5 # mm5 == x[k] - movq %mm6, %mm4 # mm4 == y[k] - movq %mm6, \reg # reg == y[k] -------------------- - pmulhw 0(%esi), %mm4 # mm4 == y[k] * (-a1) - pmulhw 8(%esi), %mm6 # mm6 == y[k] * (-a2) - pmulhw 32(%esi), %mm5 # mm5 == x[k] * b2 - paddw %mm7, %mm4 # mm4 == u1[k] -------------------- - paddw %mm6, %mm5 # mm5 == u2[k] -------------------- - .endm - - - # input in register: - # %mm0-mm3: input 4x4 pixels {x0 x1 x2 x3} - # %esi: coef memory (-a1, -a2, b0, b1, b2) in s1.14 - # %edi: state memory (u1, u2) - - # return in register: - # %mm0-mm4: 4x4 pixels result - - - - - .macro biquad_4x4_pixels - .align 16 - movq 0(%edi), %mm4 # get state - movq 8(%edi), %mm5 - df2 %mm0 # compute 4 biquads - df2 %mm1 - df2 %mm2 - df2 %mm3 - movq %mm4, 0(%edi) # store state - movq %mm5, 8(%edi) - .endm - - - - # in order to use the 4 line parallel biquad routine on horizontal - # lines, we need to reorder (rotate or transpose) the matrix, since - # images are scanline encoded, and we want to work in parallell - # on 4 lines. - # - # since the 4 lines are independent, it doesnt matter in which order - # the the vector elements are present. - # - # this allows us to use the same routine for left->right and right->left - # processing. - # - # some comments on the non-abelean group of square isometries consisting of - # (I) identity - # (H) horizontal axis mirror - # (V) vertical axis mirror - # (T) transpose (diagonal axis mirror) - # (A) antitranspose (antidiagonal axis mirror) - # (R1) 90deg anticlockwize rotation - # (R2) 180deg rotation - # (R3) 90deg clockwize rotation - # - # - # we basicly have two options: (R1,R3) or (T,A) - # we opt for T and A because they are self inverting, which improves locality - # - # use antitranspose for right to left an transpose - # for left to right (little endian) - - - # antitranspose 4x4 - - # input - # %mm3 == {d0 d1 d2 d3} - # %mm2 == {c0 c1 c2 c3} - # %mm1 == {b0 b1 b2 b3} - # %mm0 == {a0 a1 a2 a3} - - # output - # %mm3 == {a3 b3 c3 d3} - # %mm2 == {a2 b2 c2 d2} - # %mm1 == {a1 b1 c1 d1} - # %mm0 == {a0 b0 c0 d0} - - - .macro antitranspose_4x4: - movq %mm3, %mm4 - punpcklwd %mm1, %mm4 # mm4 <- {b2 d2 b3 d3} - movq %mm3, %mm5 - punpckhwd %mm1, %mm5 # mm5 <- {b0 d0 b1 d1} - - movq %mm2, %mm6 - punpcklwd %mm0, %mm6 # mm6 <- {a2 c2 a3 c3} - movq %mm2, %mm7 - punpckhwd %mm0, %mm7 # mm7 <- {a0 c0 a1 c1} - - movq %mm4, %mm3 - punpcklwd %mm6, %mm3 # mm3 <- {a3 b3 c3 d3} - movq %mm4, %mm2 - punpckhwd %mm6, %mm2 # mm2 <- {a2 b2 c2 d2} - - movq %mm5, %mm1 - punpcklwd %mm7, %mm1 # mm1 <- {a1 b1 c1 d1} - movq %mm5, %mm0 - punpckhwd %mm7, %mm0 # mm0 <- {a0 b0 c0 d0} - - .endm - - - # transpose 4x4 - - # input - # %mm3 == {d3 d2 d1 d0} - # %mm2 == {c3 c2 c1 c0} - # %mm1 == {b3 b2 b1 b0} - # %mm0 == {a3 a2 a1 a0} - - # output - # %mm3 == {d3 c3 b3 a3} - # %mm2 == {d2 c2 b2 a2} - # %mm1 == {d1 c1 b1 a1} - # %mm0 == {d0 c0 b0 a0} - - - .macro transpose_4x4: - movq %mm0, %mm4 - punpcklwd %mm2, %mm4 # mm4 <- {c1 a1 c0 a0} - movq %mm0, %mm5 - punpckhwd %mm2, %mm5 # mm5 <- {c3 a3 c2 a2} - - movq %mm1, %mm6 - punpcklwd %mm3, %mm6 # mm6 <- {d1 b1 d0 b0} - movq %mm1, %mm7 - punpckhwd %mm3, %mm7 # mm7 <- {d3 b3 d2 b2} - - movq %mm4, %mm0 - punpcklwd %mm6, %mm0 # mm0 <- {d0 c0 b0 a0} - movq %mm4, %mm1 - punpckhwd %mm6, %mm1 # mm1 <- {d1 c1 b1 a1} - - movq %mm5, %mm2 - punpcklwd %mm7, %mm2 # mm2 <- {d2 c2 b2 a2} - movq %mm5, %mm3 - punpckhwd %mm7, %mm3 # mm3 <- {d3 c3 b3 a3} - - .endm - -.globl pixel_biquad_vertb_s16 -.type pixel_biquad_vertb_s16,@function - - -# pixel_biquad_vertbr_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - - -pixel_biquad_vertb_s16: - - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %edx # line with - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - movl %edx, %eax - shll $1, %eax - addl %edx, %eax # eax = 3 * edx - - .align 16 - .biquad_vertb_line_loop: - movq (%ebx), %mm0 - movq (%ebx,%edx,1), %mm1 - movq (%ebx,%edx,2), %mm2 - movq (%ebx,%eax,1), %mm3 - biquad_4x4_pixels - movq %mm0, (%ebx) - movq %mm1, (%ebx,%edx,1) - movq %mm2, (%ebx,%edx,2) - movq %mm3, (%ebx,%eax,1) - addl %edx, %ebx - addl %eax, %ebx - decl %ecx - jnz .biquad_vertb_line_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret -.globl pixel_biquad_verbt_s16 -.type pixel_biquad_verbt_s16,@function - - -# pixel_biquad_vertbt_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - - -pixel_biquad_verbt_s16: - - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %eax # line with - - shll $3, %eax # 4 line byte spacing - decl %ecx - mul %ecx - incl %ecx - addl %eax, %ebx # ebx points to last pixblock - - movl 16(%ebp), %edx # line with - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - movl %edx, %eax - shll $1, %eax - addl %edx, %eax # eax = 3 * edx - - .align 16 - .biquad_verbt_line_loop: - movq (%ebx), %mm3 - movq (%ebx,%edx,1), %mm2 - movq (%ebx,%edx,2), %mm1 - movq (%ebx,%eax,1), %mm0 - biquad_4x4_pixels - movq %mm3, (%ebx) - movq %mm2, (%ebx,%edx,1) - movq %mm1, (%ebx,%edx,2) - movq %mm0, (%ebx,%eax,1) - subl %edx, %ebx - subl %eax, %ebx - decl %ecx - jnz .biquad_verbt_line_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - -.globl pixel_biquad_horlr_s16 -.type pixel_biquad_horlr_s16,@function -# pixel_biquad_hor_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - -pixel_biquad_horlr_s16: - - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %edx # line with - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - movl %edx, %eax - shll $1, %eax - addl %edx, %eax # eax = 3 * edx - - .align 16 - .biquad_horlr_line_loop: - movq (%ebx), %mm0 - movq (%ebx,%edx,1), %mm1 - movq (%ebx,%edx,2), %mm2 - movq (%ebx,%eax,1), %mm3 - transpose_4x4 - biquad_4x4_pixels - transpose_4x4 - movq %mm0, (%ebx) - movq %mm1, (%ebx,%edx,1) - movq %mm2, (%ebx,%edx,2) - movq %mm3, (%ebx,%eax,1) - addl $8, %ebx - decl %ecx - jnz .biquad_horlr_line_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - - -.globl pixel_biquad_horrl_s16 -.type pixel_biquad_horrl_s16,@function -# pixel_biquad_horrl_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - -pixel_biquad_horrl_s16: - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %edx # line with - - - movl %ecx, %eax - decl %eax - shll $3, %eax - addl %eax, %ebx # ebx points to last pixblock - - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - movl %edx, %eax - shll $1, %eax - addl %edx, %eax # eax = 3 * edx - - .align 16 - .biquad_horrl_line_loop: - movq (%ebx), %mm0 - movq (%ebx,%edx,1), %mm1 - movq (%ebx,%edx,2), %mm2 - movq (%ebx,%eax,1), %mm3 - antitranspose_4x4 - biquad_4x4_pixels - antitranspose_4x4 - movq %mm0, (%ebx) - movq %mm1, (%ebx,%edx,1) - movq %mm2, (%ebx,%edx,2) - movq %mm3, (%ebx,%eax,1) - subl $8, %ebx - decl %ecx - jnz .biquad_horrl_line_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - - -.globl pixel_biquad_time_s16 -.type pixel_biquad_time_s16,@function -# pixel_biquad_time_s16(short int *pixel_array, short int *s1, short int *s2, short int *coefs, int nb_4_pix_vectors) - -pixel_biquad_time_s16: - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %edx # state 1 array - movl 16(%ebp), %edi # state 2 array - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %ecx # nb of 4 pixel vectors - - - .align 16 - .biquad_time_loop: - movq (%ebx), %mm0 # get input - movq (%edx), %mm4 # get state 1 - movq (%edi), %mm5 # get state 2 - df2 %mm0 # compute direct form 2 - movq %mm0, (%ebx) # write output - movq %mm5, (%edi) # write state 2 - movq %mm4, (%edx) # write state 1 - addl $8, %ebx - addl $8, %edi - addl $8, %edx - decl %ecx - jnz .biquad_time_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - - diff --git a/system/mmx/pixel_ca_s1.s b/system/mmx/pixel_ca_s1.s deleted file mode 100644 index d9c730f..0000000 --- a/system/mmx/pixel_ca_s1.s +++ /dev/null @@ -1,189 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - - # this file contains assembler routines for 2D 1 bit cellular automata - # processing. it is organized around a feeder kernel and a - # stack based bit processor (virtual forth machine) - # - # the feeder kernel is responsable for loading/storing CA cells - # from/to memory. data in memory is organized as a scanline - # encoded toroidial bitplane (lsb = left). to simplify the kernel, the top - # left corner of the rectangular grid of pixels will shift down - # every processing step. - # - # the stack machine has the following architecture: - # CA stack: %esi, TOS: %mm0 (32x2 pixels. lsw = top row) - # CA horizon: %mm4-%mm7 (64x4 pixels. %mm4 = top row) - # - # the stack size / organization is not known to the stack machine. - # it can be thought of as operating on a 3x3 cell neightbourhood. - # the only purpose of forth program is to determine the CA local update rule. - # - # the machine is supposed to be very minimal. no looping control. - # no adressing modes. no conditional code (hey, this is an experiment!) - # so recursion is not allowed (no way to stop it) - # there are 9 words to load the cell neigbourhood on the stack. - # the rest is just logic and stack manips. - - - # this file contains pure asm macros. it is to be included before assembly - # after scaforth.pl has processed the .scaf file - - - # *************************** CA CELL ACCESS MACROS ***************************** - # fetchTL - fetchBR - - # shift / load rectangle macros: - - # shift rectangle horizontal - # result is in reg1 - .macro shift reg1 reg2 count - psllq $(32+\count), \reg1 - psrlq $(32-\count), \reg2 - psrlq $32, \reg1 - psllq $32, \reg2 - por \reg2, \reg1 - .endm - - .macro ldtop reg1 reg2 - movq %mm4, \reg1 - movq %mm5, \reg2 - .endm - - .macro ldcenter reg1 reg2 - movq %mm5, \reg1 - movq %mm6, \reg2 - .endm - - .macro ldbottom reg1 reg2 - movq %mm6, \reg1 - movq %mm7, \reg2 - .endm - - - # fetch from top row - - # fetch the top left square - .macro fetchTL - ldtop %mm0, %mm1 - shift %mm0, %mm1, -1 - .endm - - # fetch the top mid square - .macro fetchTM - ldtop %mm0, %mm1 - shift %mm0, %mm1, 0 - .endm - - # fetch the top right square - .macro fetchTR - ldtop %mm0, %mm1 - shift %mm0, %mm1, 1 - .endm - - - - # fetch from center row - - # fetch the mid left square - .macro fetchML - ldcenter %mm0, %mm1 - shift %mm0, %mm1, -1 - .endm - - # fetch the mid mid square - .macro fetchMM - ldcenter %mm0, %mm1 - shift %mm0, %mm1, 0 - .endm - - # fetch the mid right square - .macro fetchMR - ldcenter %mm0, %mm1 - shift %mm0, %mm1, 1 - .endm - - - - - - # fetch from bottom row - - # fetch the bottom left square - .macro fetchBL - ldbottom %mm0, %mm1 - shift %mm0, %mm1, -1 - .endm - - # fetch the bottom mid square - .macro fetchBM - ldbottom %mm0, %mm1 - shift %mm0, %mm1, 0 - .endm - - # fetch the bottom right square - .macro fetchBR - ldbottom %mm0, %mm1 - shift %mm0, %mm1, 1 - .endm - - - - # *************************** CA STACK MANIP MACROS ***************************** - # dup drop dropdup swap nip dropover - - .macro dup - lea -8(%esi), %esi - movq %mm0, (%esi) - .endm - - .macro drop - movq (%esi), %mm0 - lea 8(%esi), %esi - .endm - - .macro dropdup - movq (%esi), %mm0 - .endm - - .macro swap - movq (%esi), %mm1 - movq %mm0, (%esi) - movq %mm1, %mm0 - .endm - - .macro nip - lea 8(%esi), %esi - .endm - - .macro dropover - movq 8(%esi), %mm0 - .endm - - - # *************************** CA BOOLEAN LOGIC MACROS ***************************** - # overxor - - .macro overxor - pxor (%esi), %mm0 - .endm - - - - - diff --git a/system/mmx/pixel_cascade_s16.s b/system/mmx/pixel_cascade_s16.s deleted file mode 100644 index bf88d08..0000000 --- a/system/mmx/pixel_cascade_s16.s +++ /dev/null @@ -1,330 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - - - # TODO: COUPLED CASCADE SECOND ORDER SECTION - # - # s1[k] = ar * s1[k-1] + ai * s2[k-1] + x[k] - # s2[k] = ar * s2[k-1] - ai * s1[k-1] - # y[k] = c0 * x[k] + c1 * s1[k-1] + c2 * s2[k-1] - - - # MACRO: df2 - # - # computes a coupled cascade - # - # input: %mm0 == input - # %mm1 == state 1 - # %mm2 == state 2 - # (%esi) == cascade coefs (ar ai c0 c1 c2) in s0.15 - # output: %mm0 == output - # %mm1 == state 1 - # %mm2 == state 2 - - - .macro coupled - pmovq %mm1, %mm3 # mm3 == s1[k-1] - pmovq %mm1, %mm4 # mm4 == s1[k-1] - pmovq %mm2, %mm5 # mm5 == s2[k-1] - pmovq %mm2, %mm6 # mm5 == s2[k-1] - pmulhw (%esi), %mm1 # mm1 == s1[k-1] * ar - pmulhw 8(%esi), %mm3 # mm3 == s1[k-1] * ai - pmulhw 24(%esi), %mm4 # mm4 == s1[k-1] * c1 - pmulhw (%esi), %mm2 # mm2 == s2[k-1] * ar - pmulhw 8(%esi), %mm5 # mm5 == s2[k-1] * ai - pmulhw 32(%esi), %mm6 # mm6 == s2[k-1] * c2 - paddw %mm5, %mm1 # mm1 == s1[k-1] * ar + s2[k-1] * ai - psubw %mm3, %mm2 # mm2 == s2[k-1] * ar - s1[k-1] * ai == s2[k] - paddw %mm0, %mm1 # mm1 == s1[k] - pmulhw 16(%esi), %mm0 # mm0 == x[k] * c0 - paddw %mm6, %mm4 # mm4 == s1[k-1] * c1 + s2[k-1] * c2 - paddw %mm4, %mm0 # mm0 == y[k] - .endm - - - - - # in order to use the 4 line parallel cascade routine on horizontal - # lines, we need to reorder (rotate or transpose) the matrix, since - # images are scanline encoded, and we want to work in parallell - # on 4 lines. - # - # since the 4 lines are independent, it doesnt matter in which order - # the the vector elements are present. - # - # this allows us to use the same routine for left->right and right->left - # processing. - # - # some comments on the non-abelean group of square isometries consisting of - # (I) identity - # (H) horizontal axis mirror - # (V) vertical axis mirror - # (T) transpose (diagonal axis mirror) - # (A) antitranspose (antidiagonal axis mirror) - # (R1) 90deg anticlockwize rotation - # (R2) 180deg rotation - # (R3) 90deg clockwize rotation - # - # - # we basicly have two options: (R1,R3) or (T,A) - # we opt for T and A because they are self inverting, which improves locality - # - # use antitranspose for right to left an transpose - # for left to right (little endian) - - - # antitranspose 4x4 - - # input - # %mm3 == {d0 d1 d2 d3} - # %mm2 == {c0 c1 c2 c3} - # %mm1 == {b0 b1 b2 b3} - # %mm0 == {a0 a1 a2 a3} - - # output - # %mm3 == {a3 b3 c3 d3} - # %mm2 == {a2 b2 c2 d2} - # %mm1 == {a1 b1 c1 d1} - # %mm0 == {a0 b0 c0 d0} - - - .macro antitranspose_4x4: - movq %mm3, %mm4 - punpcklwd %mm1, %mm4 # mm4 <- {b2 d2 b3 d3} - movq %mm3, %mm5 - punpckhwd %mm1, %mm5 # mm5 <- {b0 d0 b1 d1} - - movq %mm2, %mm6 - punpcklwd %mm0, %mm6 # mm6 <- {a2 c2 a3 c3} - movq %mm2, %mm7 - punpckhwd %mm0, %mm7 # mm7 <- {a0 c0 a1 c1} - - movq %mm4, %mm3 - punpcklwd %mm6, %mm3 # mm3 <- {a3 b3 c3 d3} - movq %mm4, %mm2 - punpckhwd %mm6, %mm2 # mm2 <- {a2 b2 c2 d2} - - movq %mm5, %mm1 - punpcklwd %mm7, %mm1 # mm1 <- {a1 b1 c1 d1} - movq %mm5, %mm0 - punpckhwd %mm7, %mm0 # mm0 <- {a0 b0 c0 d0} - - .endm - - - # transpose 4x4 - - # input - # %mm3 == {d3 d2 d1 d0} - # %mm2 == {c3 c2 c1 c0} - # %mm1 == {b3 b2 b1 b0} - # %mm0 == {a3 a2 a1 a0} - - # output - # %mm3 == {d3 c3 b3 a3} - # %mm2 == {d2 c2 b2 a2} - # %mm1 == {d1 c1 b1 a1} - # %mm0 == {d0 c0 b0 a0} - - - .macro transpose_4x4: - movq %mm0, %mm4 - punpcklwd %mm2, %mm4 # mm4 <- {c1 a1 c0 a0} - movq %mm0, %mm5 - punpckhwd %mm2, %mm5 # mm5 <- {c3 a3 c2 a2} - - movq %mm1, %mm6 - punpcklwd %mm3, %mm6 # mm6 <- {d1 b1 d0 b0} - movq %mm1, %mm7 - punpckhwd %mm3, %mm7 # mm7 <- {d3 b3 d2 b2} - - movq %mm4, %mm0 - punpcklwd %mm6, %mm0 # mm0 <- {d0 c0 b0 a0} - movq %mm4, %mm1 - punpckhwd %mm6, %mm1 # mm1 <- {d1 c1 b1 a1} - - movq %mm5, %mm2 - punpcklwd %mm7, %mm2 # mm2 <- {d2 c2 b2 a2} - movq %mm5, %mm3 - punpckhwd %mm7, %mm3 # mm3 <- {d3 c3 b3 a3} - - .endm - -.globl pixel_cascade_vertb_s16 -.type pixel_cascade_vertb_s16,@function - - -# pixel_cascade_vertbr_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - - -pixel_cascade_vertb_s16: - - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %edx # line with - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - subl %edx, %ebx - - movq 0(%edi), %mm1 # s1[k-1] - movq 8(%edi), %mm2 # s2[k-1] - .align 16 - .cascade_vertb_line_loop: - - movq (%ebx,%edx,1), %mm3 - movq %mm3, %mm0 - addl %edx, %ebx - coupled - movq %mm0, (%ebx) - - movq (%ebx,%edx,1), %mm3 - movq %mm3, %mm0 - addl %edx, %ebx - coupled - movq %mm0, (%ebx) - - movq (%ebx,%edx,1), %mm3 - movq %mm3, %mm0 - addl %edx, %ebx - coupled - movq %mm0, (%ebx) - - movq (%ebx,%edx,1), %mm3 - movq %mm3, %mm0 - addl %edx, %ebx - coupled - movq %mm0, (%ebx) - - decl %ecx - jnz .cascade_vertb_line_loop - - movq %mm1, 0(%edi) # s1[k-1] - movq %mm2, 8(%edi) # s2[k-1] - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - -.globl pixel_cascade_horlr_s16 -.type pixel_cascade_horlr_s16,@function - - -# pixel_cascade_hor_s16(char *pixel_array, int nb_rows, int linewidth, short int coef[20], short int state[8]) - - -pixel_cascade_horlr_s16: - - - pushl %ebp - movl %esp, %ebp - push %ebx - push %esi - push %edi - - movl 8(%ebp), %ebx # pixel array offset - movl 12(%ebp), %ecx # nb of 4x4 pixblocks - movl 16(%ebp), %edx # line with - - movl 20(%ebp), %esi # coefs - movl 24(%ebp), %edi # state - - shll $1, %edx # short int addressing - movl %edx, %eax - shll $1, %eax - addl %edx, %eax # eax = 3 * edx - - - .align 16 - .cascade_horlr_line_loop: - movq (%edi), %mm1 - movq 8(%edi), %mm2 - - movq (%ebx), %mm0 - movq (%ebx,%edx,1), %mm1 - movq (%ebx,%edx,2), %mm2 - movq (%ebx,%eax,1), %mm3 - - transpose_4x4 - - movq %mm1, (%ebx,%edx,1) - movq %mm2, (%ebx,%edx,2) - movq %mm3, (%ebx,%eax,1) - - coupled - - movq %mm0, (%ebx) - movq (%ebx,%edx,1), %mm3 - movq %mm3, %mm0 - - coupled - - movq %mm0, (%ebx, %edx,1) - movq (%ebx,%edx,2), %mm3 - movq %mm3, %mm0 - - coupled - - movq %mm0, (%ebx, %edx,2) - movq (%ebx,%eax,1), %mm3 - movq %mm3, %mm0 - - coupled - - movq %mm1, 0(%edi) # s1[k-1] - movq %mm2, 8(%edi) # s2[k-1] - - movq %mm0, %mm3 - movq (%ebx), %mm0 - movq (%ebx,%edx,1), %mm1 - movq (%ebx,%edx,2), %mm2 - - transpose_4x4 - - movq %mm0, (%ebx) - movq %mm1, (%ebx,%edx,1) - movq %mm2, (%ebx,%edx,2) - movq %mm3, (%ebx,%eax,1) - - addl $8, %ebx - decl %ecx - jnz .cascade_horlr_line_loop - - emms - - pop %edi - pop %esi - pop %ebx - leave - ret - - - diff --git a/system/mmx/pixel_cheby_s16.s b/system/mmx/pixel_cheby_s16.s deleted file mode 100644 index 2afe9e2..0000000 --- a/system/mmx/pixel_cheby_s16.s +++ /dev/null @@ -1,90 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_cheby_s16_3plus -.type pixel_cheby_s16_3plus,@function - -# void pixel_cheby_s16(int *buf, int nb_8pixel_vectors, int order+1, short int *coefs) - - -# coefs are s2.13 fixed point (-4->4) -pixel_cheby_s16_3plus: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - push %edx - - movl 8(%ebp), %esi # input array - movl 12(%ebp), %ecx # vector count - movl 16(%ebp), %eax # get order+1 - - shll $3, %eax - movl 20(%ebp), %edx - addl %eax, %edx # edx = coef endx address - -# jmp skip - - .align 16 - .loop_cheby: - - movl 20(%ebp), %edi # get coefs - movq (%esi), %mm0 # load 4 pixels from memory (mm0 = x) - pcmpeqw %mm2, %mm2 - movq %mm0, %mm1 # mm1 (T_n-1) <- x - psrlw $1, %mm2 # mm2 (T_n-2) <- 1 - - - movq (%edi), %mm4 # mm4 (acc) == a0 - psraw $1, %mm4 # mm4 == a0/2 - movq %mm0, %mm5 # mm5 (intermediate) - pmulhw 8(%edi), %mm5 # mm5 == (x * a1)/2 - paddsw %mm5, %mm4 # acc = c0 + c1 x - addl $16, %edi - - .loop_cheby_inner: - movq %mm1, %mm3 # mm3 == T_n-1 - psraw $2, %mm2 # mm2 == T_n-2 / 4 - pmulhw %mm0, %mm3 # mm3 == (2 x T_n-1) / 4 - psubsw %mm2, %mm3 # mm3 == (2 x T_n-1 - T_n-2) / 4 - paddsw %mm3, %mm3 - paddsw %mm3, %mm3 # mm3 == T_n - movq %mm1, %mm2 # mm2 == new T_n-1 - movq %mm3, %mm1 # mm3 == new T_n-2 - pmulhw (%edi), %mm3 # mm3 = a_n * T_n / 2 - paddsw %mm3, %mm4 # accumulate - addl $8, %edi - cmpl %edx, %edi - jne .loop_cheby_inner - - paddsw %mm4, %mm4 # compensate for 0.125 factor - paddsw %mm4, %mm4 - paddsw %mm4, %mm4 - movq %mm4, (%esi) # store result in memory - addl $8, %esi # increment source/dest pointer - decl %ecx - jnz .loop_cheby # loop - -skip: - emms - - pop %edx - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_conv_hor_s16.s b/system/mmx/pixel_conv_hor_s16.s deleted file mode 100644 index e90a692..0000000 --- a/system/mmx/pixel_conv_hor_s16.s +++ /dev/null @@ -1,134 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - # intermediate function - - # input in register: - # %mm0: left 4 pixels - # %mm1: middle 4 pixels - # %mm2: right 4 pixels - - # %mm5: left 4 pixel masks - # %mm6: middle 4 pixel masks - # %mm7: right 4 pixel masks - - # return in register: - # %mm0: middle 4 pixels result - - - .conv_hor_4_pixels: - .align 16 - - # compute quadruplet - - # get left pixels - psrlq $48, %mm0 # shift word 3 to byte 0 - movq %mm1, %mm4 - psllq $16, %mm4 # shift word 0,1,2 to 1,2,3 - por %mm4, %mm0 # combine - pmulhw %mm5, %mm0 - psllw $1, %mm0 - - - # get middle pixels - movq %mm1, %mm4 - pmulhw %mm6, %mm4 - psllw $1, %mm4 - paddsw %mm4, %mm0 - - - # get right pixels - movq %mm2, %mm3 - psllq $48, %mm3 # shift word 0 to word 3 - movq %mm1, %mm4 - psrlq $16, %mm4 # shift word 1,2,3 to 0,1,2 - por %mm4, %mm3 # combine - pmulhw %mm7, %mm3 - psllw $1, %mm3 - paddsw %mm3, %mm0 # accumulate - - ret - -.globl pixel_conv_hor_s16 -.type pixel_conv_hor_s16,@function - - -# pixel_conv_hor_s16(short int *pixel_array, int nb_4_pixel_vectors, short int border[4], short int mask[12]) -# horizontal unsigned pixel conv (1/4 1/2 1/4) not tested -# NOT TESTED - - -pixel_conv_hor_s16: - - - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 8(%ebp), %esi # pixel array offset - movl 12(%ebp), %ecx # nb of 8 pixel vectors in a row (at least 2) - - movl 20(%ebp), %edi # mask vector - movq (%edi), %mm5 - movq 8(%edi), %mm6 - movq 16(%edi), %mm7 - - movl 16(%ebp), %edi # boundary pixel vector - - - - movq (%edi), %mm0 # init regs (left edge, so mm0 is zero) - movq (%esi), %mm1 - movq 8(%esi), %mm2 - - decl %ecx # loop has 2 terminator stubs - decl %ecx # todo: handle if ecx < 3 - - jmp .conv_line_loop - - - .align 16 - .conv_line_loop: - call .conv_hor_4_pixels # compute conv - movq %mm0, (%esi) # store result - movq %mm1, %mm0 # mm0 <- prev (%esi) - movq %mm2, %mm1 # mm1 <- 8(%esi) - movq 16(%esi), %mm2 # mm2 <- 16(%esi) - - addl $8, %esi # increase pointer - decl %ecx - jnz .conv_line_loop - - call .conv_hor_4_pixels # compute conv - movq %mm0, (%esi) # store result - movq %mm1, %mm0 # mm0 <- prev (%esi) - movq %mm2, %mm1 # mm1 <- 8(%esi) - movq (%edi), %mm2 # mm2 <- border - - call .conv_hor_4_pixels # compute last vector - movq %mm0, 8(%esi) # store it - - emms - - pop %edi - pop %esi - leave - ret - - - diff --git a/system/mmx/pixel_conv_ver_s16.s b/system/mmx/pixel_conv_ver_s16.s deleted file mode 100644 index ae2456f..0000000 --- a/system/mmx/pixel_conv_ver_s16.s +++ /dev/null @@ -1,128 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -#TODO: fix out of bound acces in conv_ver and conv_hor - - # intermediate function - - # input in register: - # %mm0: top 4 pixels - # %mm1: middle 4 pixels - # %mm2: bottom 4 pixels - - # %mm5: top 4 pixel mask - # %mm6: middle 4 pixel mask - # %mm7: bottom 4 pixel mask - - # return in register: - # %mm0: middle 4 pixels result - - - .conv_ver_4_pixels: - .align 16 - - # compute quadruplet - - # get top pixel - pmulhw %mm5, %mm0 - psllw $1, %mm0 - - # get middle pixel - movq %mm1, %mm4 - pmulhw %mm6, %mm4 - psllw $1, %mm4 - paddsw %mm4, %mm0 - - # get bottom pixel - movq %mm2, %mm3 - pmulhw %mm7, %mm3 - psllw $1, %mm3 # mm3 <- mm3/4 - paddsw %mm3, %mm0 - - ret - -.globl pixel_conv_ver_s16 -.type pixel_conv_ver_s16,@function - - -# pixel_conv_ver_s16(short int *pixel_array, int nb_4_pixel_vectors, int row_byte_size, short int border[4]) -# horizontal unsigned pixel conv (1/4 1/2 1/4) not tested -# NOT TESTED - - -pixel_conv_ver_s16: - - - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 8(%ebp), %esi # pixel array offset - movl 12(%ebp), %ecx # nb of 4 pixel vectors in a row (at least 2) - movl 16(%ebp), %edx # rowsize in bytes - - movl 24(%ebp), %edi # mask vector - movq (%edi), %mm5 - movq 8(%edi), %mm6 - movq 16(%edi), %mm7 - - movl 20(%ebp), %edi # edge vector - - - shll $1, %edx - decl %ecx # loop has a terminator stub - decl %ecx # loop has another terminator stub - - - movq (%edi), %mm0 # init regs (left edge, so mm0 is zero) - movq (%esi), %mm1 - movq (%esi,%edx,1), %mm2 - jmp .conv_line_loop - - - .align 16 - .conv_line_loop: - call .conv_ver_4_pixels # compute conv - movq %mm0, (%esi) # store result - movq %mm1, %mm0 # mm0 <- prev (%esi) - movq %mm2, %mm1 # mm1 <- (%esi,%edx,1) - movq (%esi,%edx,2), %mm2 # mm2 <- (%esi,%edx,2) - - addl %edx, %esi # increase pointer - decl %ecx - jnz .conv_line_loop - - call .conv_ver_4_pixels # compute conv - movq %mm0, (%esi) # store result - movq %mm1, %mm0 # mm0 <- prev (%esi) - movq %mm2, %mm1 # mm1 <- (%esi,%edx,1) - movq (%edi), %mm2 # clear invalid edge vector - - addl %edx, %esi # increase pointer - call .conv_ver_4_pixels # compute last vector - movq %mm0, (%esi) # store it - - emms - - pop %edi - pop %esi - leave - ret - - - diff --git a/system/mmx/pixel_crot_s16.s b/system/mmx/pixel_crot_s16.s deleted file mode 100644 index 2427869..0000000 --- a/system/mmx/pixel_crot_s16.s +++ /dev/null @@ -1,153 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_crot3d_s16 -.type pixel_crot3d_s16,@function - - -# 3 dimensional colour space rotation -# 3x3 matrix is column encoded, each coefficient is a 4x16 bit fixed point vector - -# void pixel_crot3d_s16(int *buf, int nb_4pixel_vectors_per_plane, short int *matrix) - -pixel_crot3d_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - - movl 8(%ebp), %esi # input array - movl 12(%ebp), %ecx # pixel count - movl 16(%ebp), %edi # rotation matrix - movl %ecx, %edx - shll $3, %edx # %edx = plane spacing - - - .align 16 - .loop_crot3d: - - movq (%esi), %mm0 # get 1st component - movq (%esi,%edx,1), %mm6 # get 2nd component - movq (%esi,%edx,2), %mm7 # get 3rd component - - movq %mm0, %mm1 # copy 1st component - movq %mm0, %mm2 - - pmulhw (%edi), %mm0 # mul first column - pmulhw 8(%edi), %mm1 - pmulhw 16(%edi), %mm2 - - movq %mm6, %mm5 # copy 2nd component - movq %mm6, %mm3 - - pmulhw 24(%edi), %mm6 # mul second column - pmulhw 32(%edi), %mm5 - pmulhw 40(%edi), %mm3 - - paddsw %mm6, %mm0 # accumulate - paddsw %mm5, %mm1 - paddsw %mm3, %mm2 - - movq %mm7, %mm4 # copy 3rd component - movq %mm7, %mm6 - - pmulhw 48(%edi), %mm4 # mul third column - pmulhw 56(%edi), %mm6 - pmulhw 64(%edi), %mm7 - - paddsw %mm4, %mm0 # accumulate - paddsw %mm6, %mm1 - paddsw %mm7, %mm2 - - paddsw %mm0, %mm0 # double (fixed point normalization) - paddsw %mm1, %mm1 - paddsw %mm2, %mm2 - - movq %mm0, (%esi) # store - movq %mm1, (%esi, %edx, 1) - movq %mm2, (%esi, %edx, 2) - - addl $8, %esi # increment source pointer - decl %ecx - jnz .loop_crot3d # loop - - emms - - pop %edi - pop %esi - leave - ret - - -.globl pixel_crot2d_s16 -.type pixel_crot2d_s16,@function - -# 2 dimensional colour space rotation -# 2x2 matrix is column encoded, each coefficient is a 4x16 bit fixed point vector - -# void pixel_crot2d_s16(int *buf, int nb_4pixel_vectors_per_plane, short int *matrix) - -pixel_crot2d_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - - movl 8(%ebp), %esi # input array - movl 12(%ebp), %ecx # pixel count - movl 16(%ebp), %edi # rotation matrix - movl %ecx, %edx - shll $3, %edx # %edx = plane spacing - - - .align 16 - .loop_crot2d: - - movq (%esi), %mm0 # get 1st component - movq (%esi,%edx,1), %mm2 # get 2nd component - - movq %mm0, %mm1 # copy 1st component - movq %mm2, %mm3 # copy 2nd component - - pmulhw (%edi), %mm0 # mul first column - pmulhw 8(%edi), %mm1 - - pmulhw 16(%edi), %mm2 # mul second column - pmulhw 24(%edi), %mm3 - - paddsw %mm2, %mm0 # accumulate - paddsw %mm3, %mm1 - - paddsw %mm0, %mm0 # fixed point gain correction - paddsw %mm1, %mm1 - - movq %mm0, (%esi) # store - movq %mm1, (%esi, %edx, 1) - - addl $8, %esi # increment source pointer - decl %ecx - jnz .loop_crot2d # loop - - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_gain.s b/system/mmx/pixel_gain.s deleted file mode 100644 index 5cd5057..0000000 --- a/system/mmx/pixel_gain.s +++ /dev/null @@ -1,83 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_gain -.type pixel_gain,@function - -# mmx rgba pixel gain -# void asmtest(char *pixelarray, int32 nbpixels, int *rgba_gain) -# gains are 7.9 fixed point for rgba - -pixel_gain: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 8(%ebp), %esi # pixel array offset - movl 12(%ebp), %ecx # nb of elements - movl 16(%ebp), %edi # int16[4] array of gains - - prefetch (%esi) - - emms - sarl $2, %ecx # process 4 pixels per loop iteration - jz .exit - movq (%edi), %mm7 # read gain array from memory - jmp .loop_gain - - .align 16 - .loop_gain: - - prefetch 128(%esi) - movq (%esi), %mm5 # load pixel 1-2 from memory - movq 8(%esi), %mm6 # load pixel 3-4 from memory - pxor %mm0, %mm0 # zero mm0 - mm3 - pxor %mm1, %mm1 - pxor %mm2, %mm2 - pxor %mm3, %mm3 - punpcklbw %mm5, %mm0 # unpack 1st pixel into 8.8 bit ints - punpckhbw %mm5, %mm1 # unpack 2nd - punpcklbw %mm6, %mm2 # unpack 3rd - punpckhbw %mm6, %mm3 # unpack 4th - psrlw $0x1, %mm0 # shift right to clear sign bit 9.7 - psrlw $0x1, %mm1 - psrlw $0x1, %mm2 - psrlw $0x1, %mm3 - - pmulhw %mm7, %mm0 # multiply 1st pixel 9.7 * 7.9 -> 16.0 - pmulhw %mm7, %mm1 # multiply 2nd - pmulhw %mm7, %mm2 # multiply 3rd - pmulhw %mm7, %mm3 # multiply 4th - - packuswb %mm1, %mm0 # pack & saturate to 8bit vector - movq %mm0, (%esi) # store result in memory - packuswb %mm3, %mm2 # pack & saturate to 8bit vector - movq %mm2, 8(%esi) # store result in memory - - addl $16, %esi # increment source pointer - decl %ecx - jnz .loop_gain # loop - - .exit: - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_gain_s16.s b/system/mmx/pixel_gain_s16.s deleted file mode 100644 index adcfdf5..0000000 --- a/system/mmx/pixel_gain_s16.s +++ /dev/null @@ -1,71 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_gain_s16 -.type pixel_gain_s16,@function - -# gain is integer, shift count is down -# void pixel_gain_s16(int *buf, int nb_8pixel_vectors, short int gain[4], unsigned long long *shift) - -pixel_gain_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 20(%ebp), %edi - movq (%edi), %mm6 # get shift vector - - movl 16(%ebp), %edi - movq (%edi), %mm7 # get gain vector - - movl 8(%ebp), %esi # input array - movl 12(%ebp), %ecx # pixel count - - - .align 16 - .loop_gain: - - movq (%esi), %mm0 # load 4 pixels from memory - movq %mm0, %mm1 - pmulhw %mm7, %mm1 # apply gain (s15.0) fixed point, high word - pmullw %mm7, %mm0 # low word - - movq %mm0, %mm2 # copy - movq %mm1, %mm3 - - punpcklwd %mm1, %mm0 # unpack lsw components - punpckhwd %mm3, %mm2 # unpack msw components - - psrad %mm6, %mm0 # apply signed shift - psrad %mm6, %mm2 - - packssdw %mm2, %mm0 # pack result & saturate - movq %mm0, (%esi) # store result - - - addl $8, %esi # increment source pointer - decl %ecx - jnz .loop_gain # loop - - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_mix_s16.s b/system/mmx/pixel_mix_s16.s deleted file mode 100644 index 9bf41eb..0000000 --- a/system/mmx/pixel_mix_s16.s +++ /dev/null @@ -1,68 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_mix_s16 -.type pixel_mix_s16,@function - -# mmx rgba pixel gain -# void pixel_mix_s16(int *left, int *right, int nb_4pixel_vectors, -# short int gain_left[4], short int gain_right[4]) - -pixel_mix_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 20(%ebp), %edi # int16[4] array of gains - movq (%edi), %mm6 # get left gain array - - movl 24(%ebp), %edi # int16[4] array of gains - movq (%edi), %mm7 # get right gain array - - movl 8(%ebp), %edi # left array - movl 12(%ebp), %esi # right array - movl 16(%ebp), %ecx # pixel count - - - .align 16 - .loop_mix: - -# prefetch 128(%esi) - movq (%esi), %mm1 # load right 4 pixels from memory - pmulhw %mm7, %mm1 # apply right gain - movq (%edi), %mm0 # load 4 left pixels from memory - pmulhw %mm6, %mm0 # apply left gain -# pslaw $1, %mm1 # shift left ((s).15 x (s).15 -> (s0).14)) -# pslaw $1, %mm0 - paddsw %mm0, %mm0 # no shift left arithmic, so use add instead - paddsw %mm1, %mm1 - paddsw %mm1, %mm0 # mix - movq %mm0, (%edi) - addl $8, %esi - addl $8, %edi - decl %ecx - jnz .loop_mix # loop - - emms - - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_mul_s16.s b/system/mmx/pixel_mul_s16.s deleted file mode 100644 index 240a024..0000000 --- a/system/mmx/pixel_mul_s16.s +++ /dev/null @@ -1,56 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_mul_s16 -.type pixel_mul_s16,@function - -# simple add -# void pixel_mul_s16(int *left, int *right, int nb_4pixel_vectors) - -pixel_mul_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 8(%ebp), %edi # left array - movl 12(%ebp), %esi # right array - movl 16(%ebp), %ecx # pixel count - - - .align 16 - .loop_mix: - -# prefetch 128(%esi) - movq (%esi), %mm1 # load right 4 pixels from memory - movq (%edi), %mm0 # load 4 left pixels from memory - pmulhw %mm1, %mm0 # mul - psllw $1, %mm0 # fixed point shift correction - movq %mm0, (%edi) - addl $8, %esi - addl $8, %edi - decl %ecx - jnz .loop_mix # loop - - emms - - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_pack_s16u8.s b/system/mmx/pixel_pack_s16u8.s deleted file mode 100644 index 57df702..0000000 --- a/system/mmx/pixel_pack_s16u8.s +++ /dev/null @@ -1,126 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_pack_s16u8_y -.type pixel_pack_s16u8_y,@function - -# mmx rgba pixel gain -# void pixel_pack_s16u8_y(int *input, int *output, int nb_8pixel_vectors) - -pixel_pack_s16u8_y: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - -# movl 20(%ebp), %edi # int16[4] array of gains -# movq (%edi), %mm7 # get gain array -# psllw $1, %mm7 # adjust for shifted sign bit - - movl 8(%ebp), %esi # input array - movl 12(%ebp), %edi # output array - movl 16(%ebp), %ecx # pixel count - - pxor %mm6, %mm6 - - .align 16 - .loop_pack_y: - -# prefetch 128(%esi) - movq (%esi), %mm0 # load 4 pixels from memory -# pmulhw %mm7, %mm0 # apply gain - movq 8(%esi), %mm1 # load 4 pixels from memory -# pmulhw %mm7, %mm1 # apply gain - -# movq %mm0, %mm2 -# pcmpgtw %mm6, %mm2 # mm2 > 0 ? 0xffff : 0 -# pand %mm2, %mm0 - -# movq %mm1, %mm3 -# pcmpgtw %mm6, %mm3 # mm3 > 0 ? 0xffff : 0 -# pand %mm3, %mm1 - -# psllw $1, %mm0 # shift out sign bit -# psllw $1, %mm1 # shift out sign bit - - psraw $7, %mm0 # shift to lsb - psraw $7, %mm1 # shift to lsb - - packuswb %mm1, %mm0 # pack & saturate to 8bit vector - movq %mm0, (%edi) # store result in memory - - addl $16, %esi # increment source pointer - addl $8, %edi # increment dest pointer - decl %ecx - jnz .loop_pack_y # loop - - emms - - pop %edi - pop %esi - leave - ret - -.globl pixel_pack_s16u8_uv -.type pixel_pack_s16u8_uv,@function - -pixel_pack_s16u8_uv: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - -# movl 20(%ebp), %edi # int16[4] array of gains -# movq (%edi), %mm7 # get gain array - movl 8(%ebp), %esi # pixel array offset - movl 12(%ebp), %edi # nb of elements - movl 16(%ebp), %ecx # pixel count - - pcmpeqw %mm6, %mm6 - psllw $15, %mm6 - movq %mm6, %mm5 - psrlw $8, %mm5 - por %mm5, %mm6 # mm6 <- 8 times 0x80 - - .align 16 - .loop_pack_uv: - -# prefetch 128(%esi) - movq (%esi), %mm0 # load 4 pixels from memory -# pmulhw %mm7, %mm0 # apply gain - movq 8(%esi), %mm1 # load 4 pixels from memory -# pmulhw %mm7, %mm1 # apply gain - - psraw $8, %mm0 # shift to msb - psraw $8, %mm1 - - packsswb %mm1, %mm0 # pack & saturate to 8bit vector - pxor %mm6, %mm0 # flip sign bits - movq %mm0, (%edi) # store result in memory - - addl $16, %esi # increment source pointer - addl $8, %edi # increment dest pointer - decl %ecx - jnz .loop_pack_uv # loop - - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_rand_s16.s b/system/mmx/pixel_rand_s16.s deleted file mode 100644 index 649400b..0000000 --- a/system/mmx/pixel_rand_s16.s +++ /dev/null @@ -1,76 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_rand_s16 -.type pixel_rand_s16,@function - -# mmx rgba pixel gain -# void pixel_rand_s16(int *dst, nb_4pixel_vectors, short int random_seed[4]) - -pixel_rand_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 16(%ebp), %esi # int16[4] array of random seeds - movl 8(%ebp), %edi # dst array - movl 12(%ebp), %ecx # pixel count - - movq (%esi), %mm6 - - - pcmpeqw %mm3, %mm3 - psrlw $15, %mm3 # get bit mask 4 times 0x0001 - - .align 16 - .loop_rand: - -# prefetch 128(%esi) - - - movq %mm6, %mm4 # get random vector - psrlw $15, %mm4 # get first component - movq %mm6, %mm5 - psrlw $14, %mm5 # get second component - pxor %mm5, %mm4 - movq %mm6, %mm5 - psrlw $12, %mm5 # get third component - pxor %mm5, %mm4 - movq %mm6, %mm5 - psrlw $3, %mm5 # get forth component - pxor %mm5, %mm4 - - psllw $1, %mm6 # shift left original random vector - pand %mm3, %mm4 # isolate new bit - por %mm4, %mm6 # combine into new random vector - - movq %mm6, (%edi) - addl $8, %edi - decl %ecx - jnz .loop_rand # loop - - - movq %mm6, (%esi) # store random seeds - - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_randmix_s16.s b/system/mmx/pixel_randmix_s16.s deleted file mode 100644 index 44e1702..0000000 --- a/system/mmx/pixel_randmix_s16.s +++ /dev/null @@ -1,91 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_randmix_s16 -.type pixel_randmix_s16,@function - -# mmx rgba pixel gain -# void pixel_randmix_s16(int *left, int *right, int nb_4pixel_vectors, short int random_seed[4], short int threshold[4]) - -pixel_randmix_s16: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 20(%ebp), %edi # int16[4] array of random seeds - movq (%edi), %mm6 - - movl 24(%ebp), %edi # int16[4] array of thresholds - movq (%edi), %mm7 - - movl 8(%ebp), %edi # left array - movl 12(%ebp), %esi # right array - movl 16(%ebp), %ecx # pixel count - - pcmpeqw %mm3, %mm3 - psrlw $15, %mm3 # get bit mask 4 times 0x0001 - - .align 16 - .loop_randmix: - -# prefetch 128(%esi) - movq (%esi), %mm1 # load right 4 pixels from memory - movq (%edi), %mm0 # load 4 left pixels from memory - - movq %mm6, %mm2 # get random vector - pcmpgtw %mm7, %mm2 # compare random vector with threshold - movq %mm2, %mm5 - - pand %mm0, %mm2 # get left array's components - pandn %mm1, %mm5 # get right array's components - por %mm2, %mm5 - - movq %mm5, (%edi) # store pixels - - movq %mm6, %mm4 # get random vector - psrlw $15, %mm4 # get first component - movq %mm6, %mm5 - psrlw $14, %mm5 # get second component - pxor %mm5, %mm4 - movq %mm6, %mm5 - psrlw $12, %mm5 # get third component - pxor %mm5, %mm4 - movq %mm6, %mm5 - psrlw $3, %mm5 # get forth component - pxor %mm5, %mm4 - - psllw $1, %mm6 # shift left original random vector - pand %mm3, %mm4 # isolate new bit - por %mm4, %mm6 # combine into new random vector - - addl $8, %esi - addl $8, %edi - decl %ecx - jnz .loop_randmix # loop - - - movl 20(%ebp), %edi # int16[4] array of random seeds - movq %mm6, (%edi) # store random seeds - - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_resample_s16.s b/system/mmx/pixel_resample_s16.s deleted file mode 100644 index 3959f9c..0000000 --- a/system/mmx/pixel_resample_s16.s +++ /dev/null @@ -1,314 +0,0 @@ - - -#interpolation data: -#* 4 vectors: neighbourhood for samples (TL, TR, BL, BR) -#* 2 vectors: fractional part (unsigned) -#* 2 vectors: addresses of pixel blocks - -#coord conversion data: -#1 vector: 32bit splatted address -#1 vector: 16bit splatted w-1 -#1 vector: 16bit splatted h-1 -#1 vector: 16bit splatted w (reuse w-1 with add?) -#1 dword: 32 bit line offset - -#coord generation data: several vectors for parameter update stuff.. - -#coordinate systems: 16 bit virtual coordinates (signed, center relative) -#* 2 vectors: virtual coordinates -#(evt tussenstap + conversie naar 16 bit virtual) - - -#step 1: generate virtual coords - - -#step 2: virtual coords -> block adresses + fractional adresses -#* mulhigh: real coords (x,y) (center relative) -#* add center -> unsigned (top left relative) -#* mullow: fractional part (x_frac, y_frac) -#* mulhigh, mullow, pack 32bit: y_offset -#* pack 32bit: x_offset -#* add, shift, add start address: real addresses - - -#step3: data fetch using generated addresses: -# this step would be much simpler in 4x16bit rgba. life's a bitch.. - -#step4: billinear interpolation - -#stat5: store - - - - # this can be simplified by doing 32 bit unaligned moves - # and vector unpacking on the data - - - - # cooked image data structure - # pixel environment temp storage - TL1 = 0x00 - TL2 = 0x02 - TL3 = 0x04 - TL4 = 0x06 - TR1 = 0x08 - TR2 = 0x0A - TR3 = 0x0C - TR4 = 0x0E - BL1 = 0x10 - BL2 = 0x12 - BL3 = 0x14 - BL4 = 0x16 - BR1 = 0x18 - BR2 = 0x1A - BR3 = 0x1C - BR4 = 0x1E - # addresses of pixel blocks - ADDRESS1 = 0x20 - ADDRESS2 = 0x24 - ADDRESS3 = 0x28 - ADDRESS4 = 0x2C - - # second env + address buffer (testing: not used) - SECONDBUFFER = 0x30 - - # 32bit splatted bitmap address - V2PLANEADDRESS = 0x60 - # 16bit splatted image constants - V4TWOWIDTHM1 = 0x68 - V4TWOHEIGHTM1 = 0x70 - V4LINEOFFSET = 0x78 - # data struct size - RESAMPLEDATASIZE = 0x80 - - - - # interpolation routine - # input: %mm0, %mm1 4 x 16bit unsigned top left relative virtual x and y coordinates - # %esi: temp & algo data structure - -getpixelsbilin: psrlw $1, %mm0 # convert to range 0->0x7fff [0,0.5[ - psrlw $1, %mm1 - movq %mm0, %mm2 - movq %mm1, %mm3 - movq V4TWOWIDTHM1(%esi), %mm4 # 2 * (width - 1) - movq V4TWOHEIGHTM1(%esi), %mm5 # 2 * (height - 1) - pmulhw %mm5, %mm3 # mm3 == y coord (topleft relative) - pmulhw %mm4, %mm2 # mm2 == x coord (topleft relative) - pmullw %mm5, %mm1 # mm1 == y frac (unsigned) - pmullw %mm4, %mm0 # mm0 == x frac (unsigned) - - movq %mm3, %mm5 # copy y coord - pmullw V4LINEOFFSET(%esi), %mm3 # low part of line offset - pmulhw V4LINEOFFSET(%esi), %mm5 # high part of line offset - - movq %mm2, %mm7 # copy x coord vector - pxor %mm4, %mm4 - punpcklwd %mm4, %mm2 # low part in %mm2 - punpckhwd %mm4, %mm7 # hight part in %mm7 - - movq %mm3, %mm6 # copy - punpcklwd %mm5, %mm3 # unpack low part in %mm3 - punpckhwd %mm5, %mm6 # high part int %mm6 - - paddd %mm2, %mm3 - paddd %mm7, %mm6 - pslld $1, %mm3 # convert to word adresses - pslld $1, %mm6 - - paddd V2PLANEADDRESS(%esi), %mm3 # add pixel plane address - paddd V2PLANEADDRESS(%esi), %mm6 - - movq %mm3, ADDRESS1(%esi) # store adresses - movq %mm6, ADDRESS3(%esi) - - pcmpeqw %mm2, %mm2 # all ones - movq %mm0, %mm4 # copy x frac - movq %mm1, %mm5 # copy y frac - pxor %mm2, %mm4 # compute compliment (approx negative) - pxor %mm2, %mm5 - - psrlw $1, %mm0 # shift right (0.5 * (frac x) - psrlw $1, %mm1 # shift right (0.5 * (frac y) - psrlw $1, %mm4 # shift right (0.5 * (1 - frac x) - psrlw $1, %mm5 # shift right (0.5 * (1 - frac y) - - movq %mm0, %mm2 # copy of frac x - movq %mm4, %mm3 # copy of (1-frac x) - # fetch data - - #jmp skipfetch # seems the fetch is the real killer. try to optimize this - # using 32 bit accesses & shifts - - # the src image data struct is padded to the cooked data struct - movl RESAMPLEDATASIZE(%esi), %edi - shll $1, %edi - - movl ADDRESS1(%esi), %ecx - movl ADDRESS2(%esi), %edx - - movw (%ecx), %ax - movw (%edx), %bx - movw %ax, TL1(%esi) - movw %bx, TL2(%esi) - movw 2(%ecx), %ax - movw 2(%edx), %bx - movw %ax, TR1(%esi) - movw %bx, TR2(%esi) - - addl %edi, %ecx - addl %edi, %edx - - movw (%ecx), %ax - movw (%edx), %bx - movw %ax, BL1(%esi) - movw %bx, BL2(%esi) - movw 2(%ecx), %ax - movw 2(%edx), %bx - movw %ax, BR1(%esi) - movw %bx, BR2(%esi) - - - movl ADDRESS3(%esi), %ecx - movl ADDRESS4(%esi), %edx - - - movw (%ecx), %ax - movw (%edx), %bx - movw %ax, TL3(%esi) - movw %bx, TL4(%esi) - movw 2(%ecx), %ax - movw 2(%edx), %bx - movw %ax, TR3(%esi) - movw %bx, TR4(%esi) - - addl %edi, %ecx - addl %edi, %edx - - movw (%ecx), %ax - movw (%edx), %bx - movw %ax, BL3(%esi) - movw %bx, BL4(%esi) - movw 2(%ecx), %ax - movw 2(%edx), %bx - movw %ax, BR3(%esi) - movw %bx, BR4(%esi) - - -skipfetch: - pmulhw TL1(%esi), %mm4 # bilin interpolation - pmulhw TR1(%esi), %mm0 - pmulhw BL1(%esi), %mm3 - pmulhw BR1(%esi), %mm2 - - - paddw %mm4, %mm0 - paddw %mm3, %mm2 - - pmulhw %mm5, %mm0 - pmulhw %mm1, %mm2 - - paddw %mm2, %mm0 - psllw $2, %mm0 # compensate for gain reduction - - ret - - - // linear mapping data struct - ROWSTATEX = 0x0 - ROWSTATEY = 0x8 - COLSTATEX = 0x10 - COLSTATEY = 0x18 - ROWINCX = 0x20 - ROWINCY = 0x28 - COLINCX = 0x30 - COLINCY = 0x38 - - // image data struct - LINEOFFSET = 0x0 - IMAGEADDRESS = 0x4 - WIDTH = 0x8 - HEIGHT = 0xC - IMAGEDATASIZE = 0x10 - - - -# pixel_resample_linmap_s16(void *x) -.globl pixel_resample_linmap_s16 -.type pixel_resample_linmap_s16,@function - - SOURCEIMAGE = RESAMPLEDATASIZE - DESTIMAGE = SOURCEIMAGE + IMAGEDATASIZE - LINMAPDATA = DESTIMAGE + IMAGEDATASIZE - -pixel_resample_linmap_s16: - pushl %ebp - movl %esp, %ebp - pushl %esi - pushl %edi - pushl %ebx - - - movl 8(%ebp), %esi # get data struct - movl DESTIMAGE+HEIGHT(%esi), %edx # image height - movl DESTIMAGE+IMAGEADDRESS(%esi), %edi # dest image address - movl DESTIMAGE+WIDTH(%esi), %ecx # image width - shrl $2, %ecx # vector count - .align 16 - -linmap_looprow: - movq LINMAPDATA+ROWSTATEX(%esi), %mm0 # get current coordinates - movq LINMAPDATA+ROWSTATEY(%esi), %mm1 - -linmap_loopcol: - movq %mm0, %mm4 # copy - movq %mm1, %mm5 - paddd LINMAPDATA+ROWINCX(%esi), %mm4 # increment - paddd LINMAPDATA+ROWINCY(%esi), %mm5 - movq %mm4, %mm6 # copy - movq %mm5, %mm7 - paddd LINMAPDATA+ROWINCX(%esi), %mm6 # increment - paddd LINMAPDATA+ROWINCY(%esi), %mm7 - movq %mm6, LINMAPDATA+ROWSTATEX(%esi) # store next state - movq %mm7, LINMAPDATA+ROWSTATEY(%esi) - - psrad $16, %mm0 # round to 16 bit - psrad $16, %mm1 - psrad $16, %mm4 - psrad $16, %mm5 - packssdw %mm4, %mm0 # pack new coordinates - packssdw %mm5, %mm1 - - push %ecx - push %edx - push %edi - - call getpixelsbilin # do interpolation - - pop %edi - pop %edx - pop %ecx - movq %mm0, (%edi) # store 4 pixels - addl $0x8, %edi # point to next 4 pixels - decl %ecx # dec row counter - jnz linmap_looprow - - movq LINMAPDATA+COLSTATEX(%esi), %mm0 # get column state vector - movq LINMAPDATA+COLSTATEY(%esi), %mm1 - movl DESTIMAGE+WIDTH(%esi), %ecx # image width - shrl $2, %ecx # vector count - paddd LINMAPDATA+COLINCX(%esi), %mm0 # increment - paddd LINMAPDATA+COLINCY(%esi), %mm1 - movq %mm0, LINMAPDATA+COLSTATEX(%esi) # store - movq %mm1, LINMAPDATA+COLSTATEY(%esi) - decl %edx # dec column counter - jnz linmap_loopcol - - emms - popl %ebx - popl %edi - popl %esi - leave - ret - - diff --git a/system/mmx/pixel_s1.s b/system/mmx/pixel_s1.s deleted file mode 100644 index d6bc5ca..0000000 --- a/system/mmx/pixel_s1.s +++ /dev/null @@ -1,201 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - - # this file contains ops for binary image processing - # 8x8 bit tile encoded - # low byte = bottom row - # low bit = right column - # %mm7 = scratch reg for all macros - - - # ************ load mask ******************* - # compute bit masks for rows and columns - # %mm7: scratch reg - - # load mask top - .macro ldmt count reg - pcmpeqb \reg, \reg - psllq $(64-(\count<<3)), \reg - .endm - - # load mask bottom - .macro ldmb count reg - pcmpeqb \reg, \reg - psrlq $(64-(\count<<3)), \reg - .endm - - # load mask top and bottom - .macro ldmtb count regt regb - ldmb \count, \regb - ldmt \count, \regt - .endm - - # load mask right - .macro ldmr count reg - pcmpeqb %mm7, %mm7 - psrlw $(16-\count), %mm7 - movq %mm7, \reg - psllq $8, %mm7 - por %mm7, \reg - .endm - - # load mask left - .macro ldml count reg - pcmpeqb %mm7, %mm7 - psllw $(16-\count), %mm7 - movq %mm7, \reg - psrlq $8, %mm7 - por %mm7, \reg - .endm - - # load mask left and right - .macro ldmlr count regl regr - pcmpeqb %mm7, %mm7 - psllw $(16-\count), %mm7 - movq %mm7, \regl - psrlq $8, %mm7 - por %mm7, \regl - movq \regl, \regr - psrlq $(8-\count), \regr - .endm - - # ************* shift square ********** - # shifts a square in reg, fills with zeros - - # shift square top - .macro sst count reg - psllq $(\count<<3), \reg - .endm - - # shift square bottom - .macro ssb count reg - psrlq $(\count<<3), \reg - .endm - - # not tested - # shift square left - .macro ssl count reg - movq \reg, %mm7 - pcmpeqb \reg, \reg - psllw $(16-\count), \reg - psrlw $8, \reg - pandn %mm7, \reg - psllw $(\count), \reg - .endm - - # shift square right - .macro ssr count reg - movq \reg, %mm7 - pcmpeqb \reg, \reg - psrlw $(16-\count), \reg - psllw $8, \reg - pandn %mm7, \reg - psrlw $(\count), \reg - .endm - - - # ********** combine square ************* - # combines 2 squares - - # combine right - .macro csr count regr reg - ssl \count, \reg - ssr (8-\count), \regr - por \regr, \reg - .endm - - # combine left - .macro csl count regl reg - ssr \count, \reg - ssl (8-\count), \regl - por \regl, \reg - .endm - - # combine top - .macro cst count regt reg - ssb \count, \reg - sst (8-\count), \regt - por \regt, \reg - .endm - - - # combine bottom - .macro csb count regb reg - sst \count, \reg - ssb (8-\count), \regb - por \regb, \reg - .endm - - - # ********** load combine square ************* - # loads combined square using mask - - # load combined square left - # mask should be count bits set right (i.e. 0x01) - .macro lcsml count mask source sourcel dstreg - movq \mask, \dstreg - movq \mask, %mm7 - pandn \source, \dstreg - pand \sourcel, %mm7 - psrlq $(\count), \dstreg - psllq $(8-\count), %mm7 - por %mm7, \dstreg - .endm - - - -.globl pixel_test_s1 -.type pixel_test_s1,@function - -# simple add -# void pixel_add_s16(void *dest, void *source, int nb_squares, int spacing) - - - - # - - -pixel_test_s1: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - - movl 8(%ebp), %edi # dest - movl 12(%ebp), %esi # source - movl 16(%ebp), %ecx # count - movl 20(%ebp), %edx # row distance - - ldmr 1, %mm6 - lcsml 1, %mm6, (%esi), 8(%esi), %mm0 - movq %mm0, (%edi) - - -# movq (%esi), %mm0 -# movq 8(%esi), %mm1 -# csl 4, %mm1, %mm0 -# movq %mm0, (%edi) - - emms - - - pop %edi - pop %esi - leave - ret - diff --git a/system/mmx/pixel_unpack_u8s16.s b/system/mmx/pixel_unpack_u8s16.s deleted file mode 100644 index 0fc14c2..0000000 --- a/system/mmx/pixel_unpack_u8s16.s +++ /dev/null @@ -1,113 +0,0 @@ -# Pure Data Packet mmx routine. -# Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# -.globl pixel_unpack_u8s16_y -.type pixel_unpack_u8s16_y,@function - -# mmx rgba pixel gain -# void pixel_unpack_u8s16_y(char *input, char *output, int32 nb_pixels_div8) - -pixel_unpack_u8s16_y: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - -# movl 20(%ebp), %edi # int16[4] array of gains -# movq (%edi), %mm7 # get gain array - - movl 8(%ebp), %esi # input uint8 pixel array - movl 12(%ebp), %edi # output sint16 pixel array - movl 16(%ebp), %ecx # nb of elements div 8 - - - .align 16 - .loop_unpack_y: - - movq (%esi), %mm5 # load 8 pixels from memory - pxor %mm0, %mm0 # zero mm0 - mm3 - pxor %mm1, %mm1 - punpcklbw %mm5, %mm0 # unpack 1st 4 pixels - punpckhbw %mm5, %mm1 # unpack 2nd 4 pixles - psrlw $0x1, %mm0 # shift right to clear sign bit 9.7 - psrlw $0x1, %mm1 -# pmulhw %mm7, %mm0 # apply gain -# pmulhw %mm7, %mm1 -# paddsw %mm0, %mm0 # correct factor 2 -# paddsw %mm1, %mm1 - movq %mm0, (%edi) # store - movq %mm1, 8(%edi) - - addl $8, %esi # increment source pointer - addl $16, %edi # increment dest pointer - decl %ecx - jnz .loop_unpack_y # loop - - emms - - pop %edi - pop %esi - leave - ret - -.globl pixel_unpack_u8s16_uv -.type pixel_unpack_u8s16_uv,@function -pixel_unpack_u8s16_uv: - pushl %ebp - movl %esp, %ebp - push %esi - push %edi - -# movl 20(%ebp), %edi # int16[4] array of gains -# movq (%edi), %mm7 # get gain array - - movl 8(%ebp), %esi # input uint8 pixel array - movl 12(%ebp), %edi # output sint16 pixel array - movl 16(%ebp), %ecx # nb of elements div 8 - - pcmpeqw %mm6, %mm6 - psllw $15, %mm6 - - .align 16 - .loop_unpack_uv: - - movq (%esi), %mm5 # load 8 pixels from memory - pxor %mm0, %mm0 # zero mm0 - mm3 - pxor %mm1, %mm1 - punpcklbw %mm5, %mm0 # unpack 1st 4 pixels - punpckhbw %mm5, %mm1 # unpack 2nd 4 pixles - pxor %mm6, %mm0 # flip sign bit (Cr and Cb are ofset by 128) - pxor %mm6, %mm1 -# pmulhw %mm7, %mm0 # apply gain -# pmulhw %mm7, %mm1 -# paddsw %mm0, %mm0 # correct factor 2 -# paddsw %mm1, %mm1 - movq %mm0, (%edi) # store - movq %mm1, 8(%edi) - - addl $8, %esi # increment source pointer - addl $16, %edi # increment dest pointer - decl %ecx - jnz .loop_unpack_uv # loop - - emms - - pop %edi - pop %esi - leave - ret - diff --git a/system/pdbase/Makefile b/system/pdbase/Makefile deleted file mode 100644 index 58efa41..0000000 --- a/system/pdbase/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -OBJECTS = pdp_base.o pdp_imagebase.o pdp_dpd_base.o - - -include ../../Makefile.config - -all: $(OBJECTS) - -clean: - rm -f *~ - rm -f *.o diff --git a/system/pdbase/pdp_base.c b/system/pdbase/pdp_base.c deleted file mode 100644 index 4d5593f..0000000 --- a/system/pdbase/pdp_base.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Pure Data Packet base class implementation. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* - - This file contains the pdp base class object. - This is really nothing more than an attempt to stay away from c++ - as far as possible, while having some kind of base class functionality - for pdp (tucking away the communication & thread protocol). - -*/ - -#include "pdp_base.h" -#include <stdarg.h> - - -static void pdp_base_debug(t_pdp_base *b, t_floatarg f) -{ - int i; - post("debug"); - post("inlets: %d", b->b_inlets); - post("\tpacket\tnext_packet"); - for (i=0; i<b->b_inlets; i++) - post("\t%d\t%d", b->b_packet[i], b->b_packet_next[i]); - //post("outlets: %d", b->b_inlets); -} - -static void pdp_base_thread(t_pdp_base *b, t_floatarg f) -{ - int i = (int)f; - if ((i == 0) || (i == 1)) b->b_thread_enabled = i; -} - -static void pdp_base_process(t_pdp_base *b) -{ - - if (b->b_process_method) - (*b->b_process_method)(b); -} - -/* this method is called after the thread has finished processing */ -static void pdp_base_postprocess(t_pdp_base *b) -{ - /* call the derived class postproc callback if there is any */ - if (b->b_postproc_method) - (*b->b_postproc_method)(b); - - /* unregister (mark unused) packet and propagate if packet is valid */ - if (b->b_outlet[0]) - pdp_pass_if_valid(b->b_outlet[0], &b->b_packet[0]); -} - - -/* move the passive packets in place */ -void pdp_base_movepassive(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - int i; - - /* if a cold packet was received in the meantime - swap it in, else keep the old one */ - for (i=1; i<b->b_inlets; i++){ - pdp_replace_if_valid(&b->b_packet[i], &b->b_packet_next[i]); - } - - -} - -/* the standard bang method */ -void pdp_base_bang(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - int i; - - /* if pdp thread is still processing, do nothing */ - if (-1 != b->b_queue_id) return; - - /* move packets in place */ - pdp_base_movepassive(x); - - - /* if there is a preproc method defined, call it inside - the pd thread. (mainly for allocations) */ - if (b->b_preproc_method) - (*b->b_preproc_method)(b); - - /* check if we need to use pdp queue */ - if (b->b_thread_enabled){ - - /* add the process method and callback to the process queue */ - pdp_procqueue_add(b->b_q, b, pdp_base_process, pdp_base_postprocess, &b->b_queue_id); - } - else{ - /* call both methods directly */ - pdp_base_process(b); - pdp_base_postprocess(b); - } -} - -/* hot packet input handler */ -void pdp_base_input_hot(t_pdp_base *b, t_symbol *s, t_floatarg f) -{ - - int p = (int)f; - - /* dont register if active inlet is disabled */ - if (!b->b_active_inlet_enabled) return; - - /* register the packet (readonly or read/write) - or drop it if we have an active packet - if type template is not null, packet will be converted */ - - - if (b->b_active_inlet_readonly){ - if (pdp_sym_rro() == s){ - if (b->b_type_template[0]){ - pdp_packet_convert_ro_or_drop(&b->b_packet[0], p, b->b_type_template[0]); - } - else{ - pdp_packet_copy_ro_or_drop(&b->b_packet[0], p); - } - } - } - else{ - if (pdp_sym_rrw() == s) { - if (b->b_type_template[0]){ - pdp_packet_convert_rw_or_drop(&b->b_packet[0], p, b->b_type_template[0]); - } - else{ - pdp_packet_copy_rw_or_drop(&b->b_packet[0], p); - } - } - } - - /* start processing if there is an active packet to process - and the processing method is not active */ - - if ((pdp_sym_prc() == s) && (-1 != b->b_packet[0]) && (-1 == b->b_queue_id)){ - pdp_base_bang(b); - } - //if ((pdp_sym_prc() == s) && (-1 != b->b_packet[0]) && (!b->b_dropped)) pdp_base_bang(b); - -} - -/* cold packet input handlers */ -void pdp_base_input_cold(t_pdp_base *b, t_symbol *s, int ac, t_atom *av) -{ - - int p; - int i; - char msg[] = "pdp1"; - char *c; - - int inlet; - - //post("pdp_base_input_cold: got packet"); - - /* do cheap tests first */ - if (ac != 2) return; - if (av[0].a_type != A_SYMBOL) return; - if (av[0].a_w.w_symbol != pdp_sym_rro()) return; - if (av[1].a_type != A_FLOAT) return; - p = (int)av[1].a_w.w_float; - - - /* check if it's a pdp message - and determine inlet */ - for (i=1; i<MAX_NB_PDP_BASE_INLETS; i++){ - if (s == gensym(msg)){ - inlet = i; - goto found; - } - else{ - msg[3]++; - } - } - return; - - - found: - - /* store the packet and trow away - the old one, if there is any */ - - pdp_packet_copy_ro_or_drop(&b->b_packet_next[inlet], p); -} - - -void pdp_base_set_process_method(void *x, t_pdp_method m) -{ - t_pdp_base *b = (t_pdp_base *)x; - b->b_process_method = m; -} - -void pdp_base_set_preproc_method(void *x, t_pdp_method m) -{ - t_pdp_base *b = (t_pdp_base *)x; - b->b_preproc_method = m; -} - - -void pdp_base_set_postproc_method(void *x, t_pdp_method m) -{ - t_pdp_base *b = (t_pdp_base *)x; - b->b_postproc_method = m; -} - - -void pdp_base_queue_wait(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - pdp_procqueue_wait(b->b_q); -} - -void pdp_base_set_queue(void *x, t_pdp_procqueue *q) -{ - t_pdp_base *b = (t_pdp_base *)x; - pdp_base_queue_wait(x); - b->b_q = q; -} - -t_pdp_procqueue *pdp_base_get_queue(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - return b->b_q; -} - -void pdp_base_setup(t_class *c) -{ - - /* add pdp base class methods */ - class_addmethod(c, (t_method)pdp_base_thread, gensym("thread"), A_FLOAT, A_NULL); - class_addmethod(c, (t_method)pdp_base_debug, gensym("debug"), A_NULL); - - /* hot packet handler */ - class_addmethod(c, (t_method)pdp_base_input_hot, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); - - /* cold packet handler */ - class_addanything(c, (t_method)pdp_base_input_cold); -} - -/* pdp base instance constructor */ -void pdp_base_init(void *x) -{ - int i; - t_pdp_base *b = (t_pdp_base *)x; - - b->b_channel_mask = -1; - - for(i=0; i<MAX_NB_PDP_BASE_INLETS; i++){ - b->b_packet[i] = -1; - b->b_packet_next[i] = -1; - b->b_type_template[i] = 0; - } - - b->b_queue_id = -1; - //b->b_dropped = 0; - b->b_process_method = 0; - b->b_preproc_method = 0; - b->b_inlets = 1; - b->b_outlets = 0; - b->b_active_inlet_enabled = 1; - b->b_active_inlet_readonly = 0; - b->b_thread_enabled = 1; - - // default queue is pdp queue - b->b_q = pdp_queue_get_queue(); - -} - -/* base instance destructor */ -void pdp_base_free(void *x) -{ - int i; - t_pdp_base *b = (t_pdp_base *)x; - /* remove process method from queue before deleting data */ - pdp_procqueue_finish(b->b_q, b->b_queue_id); - - /* delete stuff */ - for(i=0; i<MAX_NB_PDP_BASE_INLETS; i++){ - pdp_packet_mark_unused(b->b_packet[i]); - pdp_packet_mark_unused(b->b_packet_next[i]); - } - -} - -void pdp_base_readonly_active_inlet(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - b->b_active_inlet_readonly = 1; -} - -void pdp_base_disable_active_inlet(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - b->b_active_inlet_enabled = 0; -} - - -/* add an inlet */ -void pdp_base_add_pdp_inlet(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - char s[] = "pdp0"; - s[3] += b->b_inlets; - - if (b->b_inlets < MAX_NB_PDP_BASE_INLETS){ - inlet_new(&b->x_obj, &b->x_obj.ob_pd, gensym("pdp"), gensym(s)); - b->b_inlets++; - } - else { - post("pdp_base_add_pdp_inlet: only %d pdp inlets allowed. ignoring.", MAX_NB_PDP_BASE_INLETS); - } -} - - -/* add an outlet: only one allowed */ -t_outlet *pdp_base_add_pdp_outlet(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - t_outlet *outlet = outlet_new(&b->x_obj, &s_anything); - - - if (b->b_outlets < MAX_NB_PDP_BASE_OUTLETS){ - b->b_outlet[b->b_outlets] = outlet; - b->b_outlets++; - } - - return outlet; - -} - -void pdp_base_set_packet(void *x, int inlet, int packet) -{ - t_pdp_base *b = (t_pdp_base *)x; - - if (inlet < b->b_inlets){ - //post("%d %d", b->b_packet[inlet], b->b_packet_next[inlet]); - pdp_packet_mark_unused(b->b_packet[inlet]); - b->b_packet[inlet] = packet; - } -} - - -int pdp_base_get_packet(void *x, int inlet) -{ - t_pdp_base *b = (t_pdp_base *)x; - - if (inlet < b->b_inlets){ - //post("%d %d", b->b_packet[inlet], b->b_packet_next[inlet]); - return (b->b_packet[inlet]); - } - - return -1; -} - -int pdp_base_move_packet(void *x, int inlet) -{ - t_pdp_base *b = (t_pdp_base *)x; - int p; - - if (inlet < b->b_inlets){ - p = b->b_packet[inlet]; - b->b_packet[inlet] = -1; - return (p); - } - - return -1; -} - - - -t_object *pdp_base_get_object(void *x) -{ - return (t_object *)x; -} - -void pdp_base_add_gen_inlet(void *x, t_symbol *from, t_symbol *to) -{ - t_object *o = (t_object *)x; - inlet_new(o, &o->ob_pd, from, to); -} - -void pdp_base_disable_thread(void *x) -{ - - t_pdp_base *b = (t_pdp_base *)x; - b->b_thread_enabled = 0; -} - -void pdp_base_set_type_template(void *x, int inlet, t_pdp_symbol *type_template) -{ - t_pdp_base *b = (t_pdp_base *)x; - if (inlet < b->b_inlets){ - b->b_type_template[inlet] = type_template; - } -} diff --git a/system/pdbase/pdp_dpd_base.c b/system/pdbase/pdp_dpd_base.c deleted file mode 100644 index 162368d..0000000 --- a/system/pdbase/pdp_dpd_base.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Pure Data Packet module. DPD base class implementation. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -#include "pdp_dpd_base.h" -#include "pdp_internals.h" - - -#define THIS(b) t_pdp_dpd_base *b = (t_pdp_dpd_base *)x - - -#ifdef __cplusplus -extern "C" -{ -#endif - - - -/* PRIVATE METHODS */ - - - - -/* dpd packet context input handler */ -static void _pdp_dpd_base_context_input(t_pdp_dpd_base *b, t_symbol *s, t_floatarg f) -{ - - int p = (int)f; - int i; - - //post ("pdp_dpd_base_context_input: got %s %d", s->s_name, p); - - /* sources/sinks have active inlet disabled */ - if (b->b_dpd_active_inlet_disabled) return; - - /* handle inspect message */ - if (pdp_sym_ins() == s){ - - /* store packet for inspector */ - b->b_context_packet = p; - - /* add inspector to pdp queue - this is special: it doesn't use a command object */ - pdp_dpd_base_queue_command(b, b, b->b_inspector_method, b->b_inspector_callback, 0); - } - - /* handle accumulate message */ - if (pdp_sym_acc() == s){ - - /* store context for accumulator methods */ - b->b_context_packet = p; - - /* call bang */ - pdp_dpd_base_bang(b); - - - } - -} - -/* default command object (returns self) */ -void *_pdp_dpd_base_get_command_object(void *x){return x;} - -/* PUBLIC METHODS */ - - -void pdp_dpd_base_queue_command(void *x, void *c, t_pdp_method process, - t_pdp_method callback, int *id) -{ - THIS(b); - t_pdp_procqueue *q = pdp_base_get_queue(x); - pdp_procqueue_add(q, c, process, callback, id); - -} - -/* bang method (propagate context to outlet) : it is not registered as a pd message by default ! */ -void pdp_dpd_base_bang(void *x) -{ - THIS(b); - int i, id; - void *cobj; - - /* move passive pdp packets in place */ - pdp_base_movepassive(x); - - /* get command object (or use self) */ - cobj = b->b_command_factory_method ? (b->b_command_factory_method)(b) : b; - //post(" command object is %x. object is %x", cobj, b); - - - /* queue acc method & propagate for all outlets */ - for (i=b->b_nb_context_outlets; i--;){ - - - /* propagate the context packet to the outlet */ - if (b->b_outlet_enable[i]){ - pdp_dpd_base_queue_command(x, cobj, b->b_accum_method[i], b->b_accum_callback[i], 0); - outlet_dpd(b->b_context_outlet[i], b->b_context_packet); - } - else{ - //post("outlet %d disabled", i); - } - } - - /* queue cleanup method */ - if (b->b_cleanup_method) - //pdp_procqueue_add(b->b_q, b, b->b_cleanup_method, 0, &b->b_cleanup_queue_id); - pdp_dpd_base_queue_command(x, cobj, b->b_cleanup_method, b->b_cleanup_callback, 0); - - /* send communication complete notify */ - if (b->b_complete_notify) - (b->b_complete_notify)(x); - -} - -/* get/set context packet */ -int pdp_dpd_base_get_context_packet(void *x){ - THIS(b); - return b->b_context_packet; -} -int pdp_dpd_base_move_context_packet(void *x){ - THIS(b); - int p = b->b_context_packet; - b->b_context_packet = -1; - return p; -} - -void pdp_dpd_base_set_context_packet(void *x, int p){ - THIS(b); - pdp_packet_mark_unused(b->b_context_packet); - b->b_context_packet = p; -} - -/* add a cleanup callback (called after all propagation is finished) for sources/sinks */ -void pdp_dpd_base_add_cleanup(void *x, t_pdp_method cleanup_method, t_pdp_method cleanup_callback) -{ - THIS(b); - b->b_cleanup_method = cleanup_method; - b->b_cleanup_callback = cleanup_callback; - //b->b_cleanup_queue_id = -1; -} - -/* add a inspector callback */ -void pdp_dpd_base_add_inspector(void *x, t_pdp_method inspector_method) -{ - THIS(b); - b->b_inspector_method = inspector_method; - //b->b_inspector_queue_id = -1; -} - -/* add a context outlet */ -t_outlet *pdp_dpd_base_add_outlet(void *x, t_pdp_method accum_method, t_pdp_method accum_callback) -{ - THIS(b); - int i = b->b_nb_context_outlets; - if (i < PDP_DPD_MAX_CONTEXT_OUTLETS){ - b->b_context_outlet[i] = outlet_new((t_object *)b, &s_anything); - b->b_outlet_enable[i] = 1; - b->b_accum_method[i] = accum_method; - b->b_accum_callback[i] = accum_callback; - //b->b_accum_queue_id[i] = -1; - b->b_nb_context_outlets++; - return b->b_context_outlet[i]; - } - else{ - post("pdp_dpd_base_add_outlet: no more free outlet slots"); - return 0; - } - -} - - -/* destructor */ -void pdp_dpd_base_free(void *x) -{ - THIS(b); - - /* free base */ - pdp_base_free(b); -} - - -void pdp_dpd_base_disable_active_inlet(void *x) -{ - THIS(b); - b->b_dpd_active_inlet_disabled = 1; -} - - - -void pdp_dpd_base_enable_outlet(void *x, int outlet, int toggle) -{ - THIS(b); - if (outlet >=0 && outlet < PDP_DPD_MAX_CONTEXT_OUTLETS){ - b->b_outlet_enable[outlet] = toggle; - } - -} - - -void pdp_dpd_base_register_complete_notify(void *x, t_pdp_method method) -{ - THIS(b); - b->b_complete_notify = method; -} - -void pdp_dpd_base_register_command_factory_method(void *x, t_pdp_newmethod command_factory_method) -{ - THIS(b); - b->b_command_factory_method = command_factory_method; -} - - -/* init method */ -void pdp_dpd_base_init(void *x) -{ - THIS(b); - - /* super init */ - pdp_base_init(b); - - /* disable pdp messages on active inlet (dpd messages are used as sync) */ - pdp_base_disable_active_inlet(b); - - /* init data */ - b->b_nb_context_outlets = 0; - b->b_context_packet = -1; - b->b_cleanup_method = 0; - //b->b_cleanup_queue_id = -1; - b->b_inspector_method = 0; - //b->b_inspector_queue_id = -1; - b->b_dpd_active_inlet_disabled = 0; - - // default notify == none - b->b_complete_notify = 0; - - // default command object getter - b->b_command_factory_method = 0; - -} - - -void pdp_dpd_base_setup(t_class *class) -{ - - pdp_base_setup(class); - class_addmethod(class, (t_method)_pdp_dpd_base_context_input, gensym("dpd"), A_SYMBOL, A_FLOAT, A_NULL); - -} - -#ifdef __cplusplus -} -#endif diff --git a/system/pdbase/pdp_imagebase.c b/system/pdbase/pdp_imagebase.c deleted file mode 100644 index f9634e1..0000000 --- a/system/pdbase/pdp_imagebase.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Pure Data Packet image processor base class implementation. - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - -/* - - This file contains the pdp image base class object. -*/ - -#include "pdp_imagebase.h" -#include <stdarg.h> - - -static void pdp_imagebase_chanmask(t_pdp_base *b, t_floatarg f) -{ - int i = (int)f; - if (i < 0) i = -1; - b->b_channel_mask = i; -} - -void pdp_imagebase_setup(t_class *c) -{ - /* parent class setup */ - pdp_base_setup(c); - - /* add pdp base class methods */ - class_addmethod(c, (t_method)pdp_imagebase_chanmask, gensym("chanmask"), A_FLOAT, A_NULL); - -} - -/* pdp base instance constructor */ -void pdp_imagebase_init(void *x) -{ - int i; - t_pdp_imagebase *b = (t_pdp_imagebase *)x; - - /* init super */ - pdp_base_init(x); - - /* convert all active incoming packet types to image */ - pdp_base_set_type_template(x, 0, pdp_gensym("image/*/*")); - - /* default chanmask == all */ - b->b_channel_mask = -1; - -} - -/* base instance destructor */ -void pdp_imagebase_free(void *x) -{ - /* free super */ - pdp_base_free(x); - -} - -/* chanmask getter */ -u32 pdp_imagebase_get_chanmask(void *x) -{ - t_pdp_base *b = (t_pdp_base *)x; - return b->b_channel_mask; -} - diff --git a/system/png/Makefile b/system/png/Makefile deleted file mode 100644 index 9122da6..0000000 --- a/system/png/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -OBJECTS = pdp_png.o - - -include ../../Makefile.config - -all: $(OBJECTS) - -clean: - rm -f *~ - rm -f *.o diff --git a/system/png/pdp_png.c b/system/png/pdp_png.c deleted file mode 100644 index 573d42c..0000000 --- a/system/png/pdp_png.c +++ /dev/null @@ -1,405 +0,0 @@ - -/* - * Pure Data Packet system module. - png glue code - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "pdp.h" - -// this is an optional module -#include "pdp_config.h" - - -#ifdef HAVE_PDP_PNG -//if 0 - -#include <png.h> - -#define READING 1 -#define WRITING 2 -#define SIG_BYTES 8 - -#define D if(0) - -typedef struct -{ - FILE *x_fp; - - int x_kindof; //READING or WRITING - png_structp x_png; - png_infop x_info; - png_infop x_end_info; - - png_uint_32 x_width; - png_uint_32 x_height; - int x_bit_depth; - int x_color_type; - int x_interlace_type; - int x_compression_type; - int x_filter_type; - - int x_pdp_bitmap_type; - int x_packet; - -} t_png_image; - -static t_png_image *_init(t_png_image *x) -{ - x->x_png = 0; - x->x_info = 0; - x->x_end_info = 0; - x->x_fp = 0; - x->x_packet = -1; - return x; -} - -static int _cleanup(t_png_image *x) -{ - if (!x) return 1; - pdp_packet_mark_unused(x->x_packet); - if (x->x_png) - switch(x->x_kindof){ - case READING: png_destroy_read_struct(&x->x_png, &x->x_info, &x->x_end_info); break; - case WRITING: png_destroy_write_struct(&x->x_png, &x->x_info); break; - default: exit(1); - } - if (x->x_fp) fclose(x->x_fp); - return 1; -} - -static int _open_read(t_png_image* x, char *file) -{ - char header[SIG_BYTES]; - int is_png; - - x->x_fp = fopen(file, "r"); - if (!x->x_fp) { - D post("can't open %s for reading", file); - return 0; - } - fread(header, 1, SIG_BYTES, x->x_fp); - is_png = !png_sig_cmp(header, 0, SIG_BYTES); - - D post("%s is %s png file", file, is_png ? "a" : "not a"); - - return is_png; -} - -static int _open_write(t_png_image* x, char *file) -{ - char header[SIG_BYTES]; - int is_png; - - x->x_fp = fopen(file, "w"); - if (!x->x_fp) { - D post("can't open %s for writing", file); - return 0; - } - - return 1; -} - -/* progress callback */ - -static void _row_callback(png_structp p, png_uint_32 row, int pass) -{ - fprintf(stderr, "."); -} - -static int _initio_read(t_png_image *x) -{ - png_init_io(x->x_png, x->x_fp); - png_set_sig_bytes(x->x_png, SIG_BYTES); - D png_set_read_status_fn(x->x_png, _row_callback); - return 1; - -} - -static int _initio_write(t_png_image *x) -{ - png_init_io(x->x_png, x->x_fp); - D png_set_write_status_fn(x->x_png, _row_callback); - - return 1; - -} - -static int _checkimagetype(t_png_image *x) -{ - png_read_info(x->x_png, x->x_info); - png_get_IHDR(x->x_png, x->x_info, &x->x_width, &x->x_height, - &x->x_bit_depth, &x->x_color_type, &x->x_interlace_type, - &x->x_compression_type, &x->x_filter_type); - - D post("image info: w=%d, h=%d, depth=%d, type=%d", - (int)x->x_width, (int)x->x_height, (int)x->x_bit_depth, - (int)x->x_color_type); - - - /* handle paletted images: convert to 8 bit RGB(A) */ - if (x->x_color_type == PNG_COLOR_TYPE_PALETTE && - x->x_bit_depth <= 8) { - png_set_expand(x->x_png); - D post("convert palette"); - - /* check if there's an alpha channel and set PDP_BITMAP type */ - x->x_pdp_bitmap_type = - (png_get_valid(x->x_png, x->x_info, PNG_INFO_tRNS)) ? - PDP_BITMAP_RGBA : PDP_BITMAP_RGB; - - return 1; - } - - /* handle bitdepth */ - if (x->x_bit_depth < 8) { - png_set_expand(x->x_png); - D post("convert greyscale to 8 bit"); - } - if (x->x_bit_depth == 16){ - D post("stripping 16 bit to 8 bit"); - png_set_strip_16(x->x_png); - } - - - /* handle greyscale images */ - if (x->x_color_type == PNG_COLOR_TYPE_GRAY){ - x->x_pdp_bitmap_type = PDP_BITMAP_GREY; - if (png_get_valid(x->x_png, x->x_info, PNG_INFO_tRNS)){ - D post("no support for greyscale images with alpha info"); - return 0; - } - return 1; - } - - /* handle RGB imges */ - if (x->x_color_type = PNG_COLOR_TYPE_RGB){ - x->x_pdp_bitmap_type = PDP_BITMAP_RGB; - return 1; - } - - /* handle RGBA imges */ - if (x->x_color_type = PNG_COLOR_TYPE_RGBA){ - x->x_pdp_bitmap_type = PDP_BITMAP_RGBA; - return 1; - } - - - /* can't handle image type */ - D post("image type not supported"); - return 0; - -} - -#define user_error_ptr NULL -#define user_error_fn NULL -#define user_warning_fn NULL - -static int _buildstruct_read(t_png_image *x) -{ - x->x_kindof = READING; - - if (!(x->x_png = png_create_read_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn))) return 0; - - if (!(x->x_info = png_create_info_struct(x->x_png))) return 0; - if (!(x->x_end_info = png_create_info_struct(x->x_png))) return 0; - - return 1; -} - -static int _buildstruct_write(t_png_image *x) -{ - x->x_kindof = WRITING; - - if (!(x->x_png = png_create_write_struct - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, - user_error_fn, user_warning_fn))) return 0; - - if (!(x->x_info = png_create_info_struct(x->x_png))) return 0; - - return 1; -} - -static int _getimagedata(t_png_image *x) -{ - int nbchans = 0; - char *image_data; - png_bytep row_pointers[x->x_height]; - png_uint_32 i; - - D post("reading %d rows ", (int)x->x_height); - - switch (x->x_pdp_bitmap_type){ - case PDP_BITMAP_GREY: nbchans = 1; break; - case PDP_BITMAP_RGB: nbchans = 3; break; - case PDP_BITMAP_RGBA: nbchans = 4; break; - default: - return 0; - } - - x->x_packet = - pdp_packet_new_bitmap(x->x_pdp_bitmap_type, x->x_width, x->x_height); - if (!(image_data = pdp_packet_data(x->x_packet))) return 0; - - for(i=0; i<x->x_height; i++) - row_pointers[i] = image_data + nbchans * i * x->x_width; - - png_read_image(x->x_png, row_pointers); - - D post("DONE"); - - return 1; -} - -static int _saveimagedata(t_png_image *x, int packet) -{ - png_bytep *row_pointers; - png_uint_32 i; - int nbchans; - t_pdp *h = pdp_packet_header(packet); - char *image_data = (char *)pdp_packet_data(packet); - - if (!h) return 0; - if (PDP_BITMAP != h->type) return 0; - if (!image_data) return 0; - - x->x_width = h->info.bitmap.width; - x->x_height = h->info.bitmap.height; - - switch(h->info.image.encoding){ - case PDP_BITMAP_GREY: x->x_color_type = PNG_COLOR_TYPE_GRAY; nbchans = 1; break; - case PDP_BITMAP_RGB: x->x_color_type = PNG_COLOR_TYPE_RGB; nbchans = 3; break; - case PDP_BITMAP_RGBA: x->x_color_type = PNG_COLOR_TYPE_RGBA; nbchans = 4; break; - default: return 0; - } - - png_set_IHDR(x->x_png, x->x_info, x->x_width, x->x_height, 8, - x->x_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - png_write_info(x->x_png, x->x_info); - - D post("writing %d rows ", (int)x->x_height); - - row_pointers = (png_bytep *)pdp_alloc(sizeof(png_bytep) * x->x_height); - for(i=0; i<x->x_height; i++) - row_pointers[i] = image_data + nbchans * i * x->x_width; - - png_write_image(x->x_png, row_pointers); - png_write_end(x->x_png, x->x_info); - pdp_dealloc(row_pointers); - - D post("DONE"); - - return 1; -} - - - -/* simple functions to load and save png images */ - -int pdp_packet_bitmap_from_png_file(char *filename) -{ - int packet = -1; - t_png_image _x; - t_png_image *x = &_x; - - if (!_init(x)) goto exit; - if (!_open_read(x, filename)) goto exit; - if (!_buildstruct_read(x)) goto exit; - if (!_initio_read(x)) goto exit; - if (!_checkimagetype(x)) goto exit; - if (!_getimagedata(x)) goto exit; - - packet = x->x_packet; - x->x_packet = -1; - _cleanup(x); - return packet; - exit: - _cleanup(x); - return -1; - -} - - - -int pdp_packet_bitmap_save_png_file(int packet, char *filename) -{ - - t_png_image _x; - t_png_image *x = &_x; - - if (!_init(x)) goto exit; - if (!_open_write(x, filename)) goto exit; - if (!_buildstruct_write(x)) goto exit; - if (!_initio_write(x)) goto exit; - if (!_saveimagedata(x, packet)) goto exit; - - _cleanup(x); - return 1; - exit: - _cleanup(x); - return 0; - -} - - - -#else //PDP_HAVE_PNG -int pdp_packet_bitmap_save_png_file(int packet, char *filename) -{ - post("WARNING: no png support, can't save png file %s", filename); - return 0; -} - -int pdp_packet_bitmap_from_png_file(char *filename) -{ - post("WARNING: no png support, can't load png file %s", filename); - return -1; -} - - -#endif //PDP_HAVE_PNG - - - - - - - - - - - - - -#if 0 -int main(int argc, char **argv) -{ - char *image = 0; - - if (argc != 2) - post("usage: %s <png file>", argv[0]); - else - image = load_png(argv[1]); - - post ("%s", image ? "OK" : "ERROR"); - -} -#endif diff --git a/system/type/Makefile b/system/type/Makefile deleted file mode 100644 index 04f37a8..0000000 --- a/system/type/Makefile +++ /dev/null @@ -1,11 +0,0 @@ - -OBJECTS = pdp_bitmap.o pdp_image.o pdp_image_words.o pdp_matrix.o - - -include ../../Makefile.config - -all: $(OBJECTS) - -clean: - rm -f *~ - rm -f *.o diff --git a/system/type/pdp_bitmap.c b/system/type/pdp_bitmap.c deleted file mode 100644 index 7b093aa..0000000 --- a/system/type/pdp_bitmap.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Pure Data Packet system implementation. : 8 bit image packet implementation - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "pdp.h" -#include "pdp_internals.h" -#include <stdio.h> - - -/* the class object */ -static t_pdp_class* bitmap_class; - - -t_bitmap *pdp_packet_bitmap_info(int packet) -{ - return (t_bitmap *)pdp_packet_subheader(packet); -} - -/* check if packet is a valid image packet */ -int pdp_packet_bitmap_isvalid(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *image = pdp_packet_bitmap_info(packet); - if (!header) return 0; - if (PDP_BITMAP != header->type) return 0; - - return 1; - -} - - - -/* bitmap constructors */ -t_pdp_symbol *pdp_packet_bitmap_get_description(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - char description[1024]; - char *c = description; - int encoding; - - if (!header) return pdp_gensym("invalid"); - else if (!header->desc){ - /* if description is not defined, try to reconstruct it (for backwards compat) */ - if (header->type == PDP_BITMAP){ - c += sprintf(c, "bitmap"); - encoding = bitmap->encoding; - switch(encoding){ - case PDP_BITMAP_RGB: c += sprintf(c, "/rgb"); break; - case PDP_BITMAP_RGBA: c += sprintf(c, "/rgba"); break; - case PDP_BITMAP_GREY: c += sprintf(c, "/grey"); break; - case PDP_BITMAP_YV12: c += sprintf(c, "/yv12"); break; - default: - c += sprintf(c, "/unknown"); goto exit; - } - c += sprintf(c, "/%dx%d", - bitmap->width, - bitmap->height); - exit: - return pdp_gensym(description); - } - else return pdp_gensym("unknown"); - } - else return header->desc; -} - -int pdp_packet_new_bitmap_yv12(u32 w, u32 h) -{ - t_pdp *header; - t_bitmap *bitmap; - int packet; - - - u32 size = w*h; - u32 totalnbpixels = size; - u32 packet_size = size + (size >> 1); - - packet = pdp_packet_new(PDP_BITMAP, packet_size); - header = pdp_packet_header(packet); - bitmap = pdp_packet_bitmap_info(packet); - if (!header) return -1; - - bitmap->encoding = PDP_BITMAP_YV12; - bitmap->width = w; - bitmap->height = h; - header->desc = pdp_packet_bitmap_get_description(packet); - header->theclass = bitmap_class; - - return packet; -} - -int pdp_packet_new_bitmap_grey(u32 w, u32 h) -{ - t_pdp *header; - t_bitmap *bitmap; - int packet; - - u32 size = w*h; - u32 totalnbpixels = size; - u32 packet_size = totalnbpixels; - - packet = pdp_packet_new(PDP_BITMAP, packet_size); - header = pdp_packet_header(packet); - bitmap = pdp_packet_bitmap_info(packet); - if (!header) return -1; - - bitmap->encoding = PDP_BITMAP_GREY; - bitmap->width = w; - bitmap->height = h; - header->desc = pdp_packet_bitmap_get_description(packet); - header->theclass = bitmap_class; - - return packet; -} - -int pdp_packet_new_bitmap_rgb(u32 w, u32 h) -{ - t_pdp *header; - t_bitmap *bitmap; - int packet; - - - u32 size = w*h; - u32 totalnbpixels = size; - u32 packet_size = totalnbpixels * 3; - - packet = pdp_packet_new(PDP_BITMAP, packet_size); - header = pdp_packet_header(packet); - bitmap = pdp_packet_bitmap_info(packet); - if (!header) return -1; - - bitmap->encoding = PDP_BITMAP_RGB; - bitmap->width = w; - bitmap->height = h; - header->desc = pdp_packet_bitmap_get_description(packet); - header->theclass = bitmap_class; - - return packet; -} - -int pdp_packet_new_bitmap_rgba(u32 w, u32 h) -{ - t_pdp *header; - t_bitmap *bitmap; - int packet; - - - u32 size = w*h; - u32 totalnbpixels = size; - u32 packet_size = totalnbpixels * 4; - - packet = pdp_packet_new(PDP_BITMAP, packet_size); - header = pdp_packet_header(packet); - bitmap = pdp_packet_bitmap_info(packet); - if (!header) return -1; - - bitmap->encoding = PDP_BITMAP_RGBA; - bitmap->width = w; - bitmap->height = h; - header->desc = pdp_packet_bitmap_get_description(packet); - header->theclass = bitmap_class; - - return packet; -} - -int pdp_packet_new_bitmap(int type, u32 w, u32 h) -{ - switch(type){ - case PDP_BITMAP_GREY: return pdp_packet_new_bitmap_grey(w,h); - case PDP_BITMAP_RGB: return pdp_packet_new_bitmap_rgb(w,h); - case PDP_BITMAP_RGBA: return pdp_packet_new_bitmap_rgba(w,h); - default: return -1; - } -} - - -/* some utility methods */ -void pdp_llconv_flip_top_bottom(char *data, int width, int height, int pixelsize); - -/* flip top & bottom */ -void pdp_packet_bitmap_flip_top_bottom(int packet) -{ - t_bitmap *b = (t_bitmap *)pdp_packet_subheader(packet); - char *d = (char *)pdp_packet_data(packet); - int w,h; - if (!pdp_packet_bitmap_isvalid(packet)) return; - if (!b) return; - w = b->width; - h = b->height; - - switch(b->encoding){ - case PDP_BITMAP_GREY: pdp_llconv_flip_top_bottom(d,w,h,1); break; - case PDP_BITMAP_RGB: pdp_llconv_flip_top_bottom(d,w,h,3); break; - case PDP_BITMAP_RGBA: pdp_llconv_flip_top_bottom(d,w,h,4); break; - default: break; - } - -} - - - -/* conversion methods */ -// image/grey/* -> bitmap/grey/* -static int _pdp_packet_bitmap_convert_grey_to_grey8(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - s16 *data = (s16 *)pdp_packet_data(packet); - u8 *new_data; - u32 w,h; - int new_p; - - if (!pdp_packet_image_isvalid(packet)) return -1; - w = image->width; - h = image->height; - - if (!((image->encoding == PDP_IMAGE_GREY) || - (image->encoding == PDP_IMAGE_YV12))) return -1; - - new_p = pdp_packet_new_bitmap_grey(w,h); - if (-1 == new_p) return -1; - new_data = (u8 *)pdp_packet_data(new_p); - - /* convert image to greyscale 8 bit */ - pdp_llconv(data,RIF_GREY______S16, new_data, RIF_GREY______U8, w, h); - - return new_p; -} - -static int _pdp_packet_bitmap_convert_YCrCb_to_rgb8(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - s16 *data = (s16 *)pdp_packet_data(packet); - u8 *new_data; - u32 w,h; - int new_p; - - if (!pdp_packet_image_isvalid(packet)) return -1; - w = image->width; - h = image->height; - - if (!((image->encoding == PDP_IMAGE_YV12))) return -1; - - new_p = pdp_packet_new_bitmap_rgb(w,h); - if (-1 == new_p) return -1; - new_data = (u8 *)pdp_packet_data(new_p); - - /* convert image to greyscale 8 bit */ - pdp_llconv(data,RIF_YVU__P411_S16, new_data, RIF_RGB__P____U8, w, h); - - return new_p; -} - -static int _pdp_packet_bitmap_convert_image_to_yv12(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - s16 *data = (s16 *)pdp_packet_data(packet); - u8 *new_data; - u32 w,h, nbpixels; - int new_p; - int encoding = image->encoding; - - if (!pdp_packet_image_isvalid(packet)) return -1; - w = image->width; - h = image->height; - nbpixels = w*h; - - new_p = pdp_packet_new_bitmap_yv12(w,h); - if (-1 == new_p) return -1; - new_data = (u8 *)pdp_packet_data(new_p); - - switch (encoding){ - case PDP_IMAGE_YV12: - pdp_llconv(data, RIF_YVU__P411_S16, new_data, RIF_YVU__P411_U8, w, h); - break; - case PDP_IMAGE_GREY: - pdp_llconv(data, RIF_GREY______S16, new_data, RIF_GREY______U8, w, h); - memset(new_data + nbpixels, 0x80, nbpixels>>1); - break; - default: - /* not supported, $$$TODO add more */ - pdp_packet_mark_unused(new_p); - new_p = -1; - break; - } - - return new_p; - -} - -static int _pdp_packet_bitmap_convert_rgb8_to_YCrCb(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - u8 *data = (u8 *)pdp_packet_data(packet); - s16 *new_data; - u32 w,h; - int new_p; - - w = bitmap->width; - h = bitmap->height; - new_p = pdp_packet_new_image_YCrCb(w,h); - if (-1 == new_p) return -1; - new_data = (s16 *)pdp_packet_data(new_p); - - /* convert image to greyscale 8 bit */ - pdp_llconv(data, RIF_RGB__P____U8, new_data, RIF_YVU__P411_S16, w, h); - - return new_p; -} - -static int _pdp_packet_bitmap_convert_rgb8_to_bitmap_YCrCb(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - u8 *data = (u8 *)pdp_packet_data(packet); - u8 *new_data; - u32 w,h; - int new_p; - - w = bitmap->width; - h = bitmap->height; - new_p = pdp_packet_new_bitmap_yv12(w,h); - if (-1 == new_p) return -1; - new_data = (u8 *)pdp_packet_data(new_p); - - /* convert image to greyscale 8 bit */ - pdp_llconv(data, RIF_RGB__P____U8, new_data, RIF_YVU__P411_U8, w, h); - - return new_p; -} - -static int _pdp_packet_bitmap_convert_grey8_to_grey(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - s16 *data = (s16 *)pdp_packet_data(packet); - u8 *new_data; - u32 w,h; - int new_p; - - w = bitmap->width; - h = bitmap->height; - new_p = pdp_packet_new_image_grey(w,h); - if (-1 == new_p) return -1; - new_data = (u8 *)pdp_packet_data(new_p); - - /* convert image to greyscale 8 bit */ - pdp_llconv(data, RIF_GREY______U8, new_data, RIF_GREY______S16, w, h); - - return new_p; -} -static int _pdp_packet_bitmap_convert_rgb8_to_rgba8(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - u8 *data = (u8 *)pdp_packet_data(packet); - u8 *new_data; - int w,h, new_p, i; - - w = bitmap->width; - h = bitmap->height; - new_p = pdp_packet_new_bitmap_rgba(w,h); - if (-1 == new_p) return -1; - new_data = (u8 *)pdp_packet_data(new_p); - - for(i=0; i<w*h; i++){ - new_data[4*i+0] = data[3*i + 0]; - new_data[4*i+1] = data[3*i + 1]; - new_data[4*i+2] = data[3*i + 2]; - new_data[4*i+3] = 0; - } - - return new_p; -} -static int _pdp_packet_bitmap_convert_rgba8_to_rgb8(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - u8 *data = (u8 *)pdp_packet_data(packet); - u8 *new_data; - int w,h, new_p, i; - - w = bitmap->width; - h = bitmap->height; - new_p = pdp_packet_new_bitmap_rgb(w,h); - if (-1 == new_p) return -1; - new_data = (u8 *)pdp_packet_data(new_p); - - for(i=0; i<w*h; i++){ - new_data[3*i+0] = data[4*i + 0]; - new_data[3*i+1] = data[4*i + 1]; - new_data[3*i+2] = data[4*i + 2]; - } - - return new_p; -} -static int _pdp_packet_bitmap_convert_rgb8_to_mchp(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - u8 *data = (u8 *)pdp_packet_data(packet); - s16 *new_data; - int w,h; - int new_p, i, plane; - - w = bitmap->width; - h = bitmap->height; - plane = w*h; - new_p = pdp_packet_new_image_multi(w,h,3); - if (-1 == new_p) return -1; - new_data = (s16 *)pdp_packet_data(new_p); - - for(i=0; i<w*h; i++){ - new_data[i] = ((u32)data[3*i + 0]) << 7; - new_data[i+plane] = ((u32)data[3*i + 1]) << 7; - new_data[i+plane*2] = ((u32)data[3*i + 2]) << 7; - } - - return new_p; -} - -static int _pdp_packet_bitmap_convert_yv12_to_image(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_bitmap *bitmap = pdp_packet_bitmap_info(packet); - u8 *data = (u8 *)pdp_packet_data(packet); - s16 *new_data; - int w,h; - int new_p; - - w = bitmap->width; - h = bitmap->height; - new_p = pdp_packet_new_image_YCrCb(w,h); - new_data = pdp_packet_data(new_p); - if (-1 == new_p || !new_data) return -1; - pdp_llconv(data, RIF_YVU__P411_U8, new_data, RIF_YVU__P411_S16, w, h); - - return new_p; -} - -static int _pdp_packet_bitmap_convert_mchp_to_rgb8(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = (t_image *)pdp_packet_subheader(packet); - s16 *data = (s16 *)pdp_packet_data(packet); - u8 *new_data; - int w = image->width; - int h = image->height; - int plane = w*h; - int nb_channels = image->depth; - int new_p, i; - - static inline u8 _map(s32 pixel){ - s32 mask = ~(pixel>>16); - return ((pixel >> 7) & mask); - } - - switch(nb_channels){ - default: return -1; - case 1: - if (-1 == (new_p = pdp_packet_new_bitmap_grey(w,h))) return -1; - new_data = (u8*)pdp_packet_data(new_p); - for(i=0; i<plane; i++) new_data[i] = _map(data[i]); - break; - case 3: - if (-1 == (new_p = pdp_packet_new_bitmap_rgb(w,h))) return -1; - new_data = (u8*)pdp_packet_data(new_p); - for(i=0; i<plane; i++){ - new_data[3*i+0] = _map(data[i]); - new_data[3*i+1] = _map(data[i+plane]); - new_data[3*i+2] = _map(data[i+plane*2]); - } - break; - case 4: - if (-1 == (new_p = pdp_packet_new_bitmap_rgba(w,h))) return -1; - new_data = (u8*)pdp_packet_data(new_p); - for(i=0; i<plane; i++){ - new_data[4*i+0] = _map(data[i]); - new_data[4*i+1] = _map(data[i+plane]); - new_data[4*i+2] = _map(data[i+plane*2]); - new_data[4*i+3] = _map(data[i+plane*3]); - } - break; - - - } - - return new_p; - -} - -static int _pdp_packet_bitmap_convert_fallback(int packet, t_pdp_symbol *dest_template) -{ - post("can't convert image type %s to %s", - pdp_packet_get_description(packet)->s_name, dest_template->s_name); - - return -1; -} - -static int pdp_bitmap_factory(t_pdp_symbol *type) -{ - return -1; -} - -void pdp_bitmap_setup(void) -{ - t_pdp_conversion_program *program; - - /* setup class object */ - bitmap_class = pdp_class_new(pdp_gensym("bitmap/*/*"), pdp_bitmap_factory); - - - /* setup conversion programs */ - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_grey_to_grey8, 0); - pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("bitmap/grey/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_grey8_to_grey, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/grey/*"), pdp_gensym("image/grey/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_YCrCb_to_rgb8, 0); - pdp_type_register_conversion(pdp_gensym("image/YCrCb/*"), pdp_gensym("bitmap/rgb/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_image_to_yv12, 0); - pdp_type_register_conversion(pdp_gensym("image/YCrCb/*"), pdp_gensym("bitmap/yv12/*"), program); - pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("bitmap/yv12/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_yv12_to_image, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/yv12/*"), pdp_gensym("image/YCrCb/*"), program); - - /* rgb->YCrCb converts the colour space */ - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_YCrCb, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("image/YCrCb/*"), program); - - - /* rgb <-> multi does not convert the colour space */ - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_mchp, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("image/multi/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_mchp_to_rgb8, 0); - pdp_type_register_conversion(pdp_gensym("image/multi/*"), pdp_gensym("bitmap/*/*"), program); - - - /* rgb <-> rgba */ - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_rgba8, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("bitmap/rgba/*"), program); - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgba8_to_rgb8, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/rgba/*"), pdp_gensym("bitmap/rgb/*"), program); - - - /* fallback rgb convertor */ - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_YCrCb, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("image/*/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_rgb8_to_bitmap_YCrCb, 0); - pdp_type_register_conversion(pdp_gensym("bitmap/rgb/*"), pdp_gensym("bitmap/yv12/*"), program); - - - /* fallbacks */ - program = pdp_conversion_program_new(_pdp_packet_bitmap_convert_fallback, 0); - pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("bitmap/*/*"), program); - pdp_type_register_conversion(pdp_gensym("bitmap/*/*"), pdp_gensym("image/*/*"), program); - pdp_type_register_conversion(pdp_gensym("bitmap/*/*"), pdp_gensym("bitmap/*/*"), program); - -} diff --git a/system/type/pdp_image.c b/system/type/pdp_image.c deleted file mode 100644 index 1aa9763..0000000 --- a/system/type/pdp_image.c +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Pure Data Packet system implementation. : 16 bit image packet implementation - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - This file contains methods for the image packets - pdp_packet_new_* methods are several image packet constructors - pdp_type_* are image type checkers & converters - -*/ - -#include "pdp.h" -#include "pdp_internals.h" -#include <stdio.h> - - -/* the class object */ -static t_pdp_class* image_class; - - - -/* check dimensions */ -static void _checkdim(u32 width, u32 height){ - if ((pdp_imageproc_legalwidth(width) != width) || - (pdp_imageproc_legalheight(height) != height)){ - post("WARNING: request to create image packet with illegal dimensions %d x %d", width, height); - } -} - - -/* image packet constructors */ -int pdp_packet_new_image_YCrCb(u32 w, u32 h) -{ - t_pdp *header; - t_image *image; - int packet; - - - u32 size = w*h; - u32 totalnbpixels = size + (size >> 1); - u32 packet_size = totalnbpixels << 1; - - _checkdim(w,h); - - packet = pdp_packet_new(PDP_IMAGE, packet_size); - header = pdp_packet_header(packet); - image = pdp_packet_image_info(packet); - if (!header) return -1; - - image->encoding = PDP_IMAGE_YV12; - image->width = w; - image->height = h; - header->desc = pdp_packet_image_get_description(packet); - header->theclass = image_class; - - return packet; -} - -int pdp_packet_new_image_grey(u32 w, u32 h) -{ - t_pdp *header; - t_image *image; - int packet; - - - u32 size = w*h; - u32 totalnbpixels = size; - u32 packet_size = totalnbpixels << 1; - - _checkdim(w,h); - - packet = pdp_packet_new(PDP_IMAGE, packet_size); - header = pdp_packet_header(packet); - image = pdp_packet_image_info(packet); - if (!header) return -1; - - image->encoding = PDP_IMAGE_GREY; - image->width = w; - image->height = h; - header->desc = pdp_packet_image_get_description(packet); - header->theclass = image_class; - - return packet; -} - -int pdp_packet_new_image_mchp(u32 w, u32 h, u32 d) -{ - t_pdp *header; - t_image *image; - int packet; - - - u32 size = w*h*d; - u32 totalnbpixels = size; - u32 packet_size = totalnbpixels << 1; - - _checkdim(w,h); - - packet = pdp_packet_new(PDP_IMAGE, packet_size); - header = pdp_packet_header(packet); - image = pdp_packet_image_info(packet); - if (!header) return -1; - - - image->encoding = PDP_IMAGE_MCHP; - image->width = w; - image->height = h; - image->depth = d; - header->desc = pdp_packet_image_get_description(packet); - header->theclass = image_class; - - return packet; -} - - -int pdp_packet_new_image(u32 type, u32 w, u32 h) -{ - switch (type){ - case PDP_IMAGE_YV12: - return pdp_packet_new_image_YCrCb(w,h); - case PDP_IMAGE_GREY: - return pdp_packet_new_image_grey(w,h); - default: - return -1; - } -} - - -/****************** packet type checking and conversion methods ********************/ - - - -/* check if two image packets are allocated and of the same type */ -int pdp_packet_image_compat(int packet0, int packet1) -{ - t_pdp *header0 = pdp_packet_header(packet0); - t_pdp *header1 = pdp_packet_header(packet1); - t_image *image0 = pdp_packet_image_info(packet0); - t_image *image1 = pdp_packet_image_info(packet1); - - - if (!(pdp_packet_compat(packet0, packet1))) return 0; - if (header0->type != PDP_IMAGE){ - //post("pdp_type_compat_image: not a PDP_IMAGE"); - return 0; - } - if (image0->encoding != image1->encoding){ - //post("pdp_type_compat_image: encodings differ"); - return 0; - } - if (image0->width != image1->width){ - //post("pdp_type_compat_image: image withs differ"); - return 0; - } - if (image0->height != image1->height){ - //post("pdp_type_compat_image: image heights differ"); - return 0; - } - return 1; -} - -/* check if packet is a valid image packet */ -int pdp_packet_image_isvalid(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - if (!header) return 0; - if (PDP_IMAGE != header->type) return 0; - if ((PDP_IMAGE_YV12 != image->encoding) - && (PDP_IMAGE_GREY != image->encoding) - && (PDP_IMAGE_MCHP != image->encoding)) return 0; - - return 1; - -} - -/* set the channel mask for the image */ -void pdp_packet_image_set_chanmask(int packet, unsigned int chanmask) -{ - if (pdp_packet_image_isvalid(packet)) pdp_packet_image_info(packet)->chanmask = chanmask; - -} - - -t_image *pdp_packet_image_info(int packet) -{ - return (t_image *)pdp_packet_subheader(packet); -} - - -t_pdp_symbol *pdp_packet_image_get_description(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - char description[1024]; - char *c = description; - int encoding; - - if (!header) return pdp_gensym("invalid"); - else if (!header->desc){ - /* if description is not defined, try to reconstruct it (for backwards compat) */ - if (header->type == PDP_IMAGE){ - c += sprintf(c, "image"); - encoding = image->encoding; - switch(encoding){ - case PDP_IMAGE_YV12: c += sprintf(c, "/YCrCb"); break; - case PDP_IMAGE_GREY: c += sprintf(c, "/grey"); break; - case PDP_IMAGE_MCHP: c += sprintf(c, "/multi"); break; - default: - c += sprintf(c, "/unknown"); goto exit; - } - if (encoding == PDP_IMAGE_MCHP){ - c += sprintf(c, "/%dx%dx%d", - image->width, - image->height, - image->depth); - } - else { - c += sprintf(c, "/%dx%d", - image->width, - image->height); - } - - exit: - return pdp_gensym(description); - } - else return pdp_gensym("unknown"); - } - else return header->desc; -} - - - - - -/* IMAGE PACKAGE CONVERSION ROUTINES */ - -/* note: these are internal: no extra checking is done - it is assumed the packets are of correct type (the type template associated with the conversion program) */ - -// image/YCrCb/* -> image/grey/* -// image/multi/* -> image/grey/* (only first channel) -static int _pdp_packet_image_convert_YCrCb_to_grey(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - int w = image->width; - int h = image->height; - int p = pdp_packet_new_image_grey(w,h); - if (p == -1) return p; - memcpy(pdp_packet_data(p), pdp_packet_data(packet), 2*w*h); - return p; -} - -// image/grey/* -> image/YCrCb/* -static int _pdp_packet_image_convert_grey_to_YCrCb(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - int w = image->width; - int h = image->height; - int p = pdp_packet_new_image_YCrCb(w,h); - int y_bytes = 2*w*h; - void *data; - if (p == -1) return p; - data = pdp_packet_data(p); - memcpy(data, pdp_packet_data(packet), y_bytes); - memset(data+y_bytes, 0, y_bytes >> 1); - return p; -} - -// image/grey/* -> image/multi/* -static int _pdp_packet_image_convert_grey_to_multi(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - int w = image->width; - int h = image->height; - int p = pdp_packet_new_image_mchp(w,h,1); - int y_bytes = 2*w*h; - void *data; - if (p == -1) return p; - data = pdp_packet_data(p); - memcpy(data, pdp_packet_data(packet), y_bytes); - return p; -} - -// image/multi/* -> image/YCrCb/* (only first 3 channels) -static int _pdp_packet_image_convert_multi_to_YCrCb(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - s16 *data, *newdata; - - /* get info */ - int w = image->width; - int h = image->height; - int d = image->depth; - int plane_size = w*h; - - /* create new packet */ - int newpacket = pdp_packet_new_image_YCrCb(w, h); - if (-1 == newpacket) return -1; - - data = pdp_packet_data(packet); - newdata = pdp_packet_data(newpacket); - - /* copy channel 0 */ - memcpy(newdata, data, plane_size<<1); - newdata += plane_size; - data += plane_size; - - /* copy channel 1 */ - if (d >= 1) pdp_resample_halve(data, newdata, w, h); - else memset(newdata, 0, plane_size >> 1); - data += plane_size; - newdata += (plane_size >> 2); - - - /* copy channel 2 */ - if (d >= 2) pdp_resample_halve(data, newdata, w, h); - else memset(newdata, 0, plane_size >> 1); - - return newpacket; - -} - -// image/YCrCb/* -> image/multi/* -static int _pdp_packet_image_convert_YCrCb_to_multi(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - s16 *data, *newdata; - - /* get info */ - int w = image->width; - int h = image->height; - int plane_size = w*h; - - /* create new packet */ - int newpacket = pdp_packet_new_image_mchp(w, h, 3); - if (-1 == newpacket) return -1; - - data = pdp_packet_data(packet); - newdata = pdp_packet_data(newpacket); - - /* copy channel 0 */ - memcpy(newdata, data, plane_size<<1); - newdata += plane_size; - data += plane_size; - w >>= 1; - h >>= 1; - - /* copy channel 1 */ - pdp_resample_double(data, newdata, w, h); - data += (plane_size >> 2); - newdata += plane_size; - - /* copy channel 2 */ - pdp_resample_double(data, newdata, w, h); - - return newpacket; - -} - -static void _pdp_description_get_dims(t_pdp_symbol *template, int *w, int *h, int *d) -{ - char *c = template->s_name; - // get requested dimensions - *w = 0; - *h = 0; - *d = 0; - while (*c++ != '/'); - while (*c++ != '/'); - sscanf(c, "%dx%dx%d", w, h, d); - -} - -// resample image/YCrCb/* -static int _pdp_packet_image_convert_resample_YCrCb(int packet, t_pdp_symbol *dest_template) -{ - int quality = 1; - int dst_w, dst_h, dummy; - int new_packet; - unsigned int src_size, src_voffset, src_uoffset; - unsigned int dst_size, dst_voffset, dst_uoffset; - t_pdp *header0 = pdp_packet_header(packet); - t_image *image0 = pdp_packet_image_info(packet); - unsigned int src_w = image0->width; - unsigned int src_h = image0->height; - short int *src_image = (short int *)pdp_packet_data(packet); - short int *dst_image; - _pdp_description_get_dims(dest_template, &dst_w, &dst_h, &dummy); - new_packet = pdp_packet_new_image_YCrCb(dst_w, dst_h); - if (-1 == new_packet) return -1; - dst_image = (short int*)pdp_packet_data(new_packet); - src_size = src_w*src_h; - src_voffset = src_size; - src_uoffset = src_size + (src_size>>2); - dst_size = dst_w*dst_h; - dst_voffset = dst_size; - dst_uoffset = dst_size + (dst_size>>2); - if (quality){ - pdp_resample_scale_bilin(src_image, dst_image, src_w, src_h, dst_w, dst_h); - pdp_resample_scale_bilin(src_image+src_voffset, dst_image+dst_voffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); - pdp_resample_scale_bilin(src_image+src_uoffset, dst_image+dst_uoffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); - } - else{ - pdp_resample_scale_nn(src_image, dst_image, src_w, src_h, dst_w, dst_h); - pdp_resample_scale_nn(src_image+src_voffset, dst_image+dst_voffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); - pdp_resample_scale_nn(src_image+src_uoffset, dst_image+dst_uoffset, src_w>>1, src_h>>1, dst_w>>1, dst_h>>1); - } - return new_packet; -} - -// resample image/grey/* and image/multi/* -static int _pdp_packet_image_convert_resample_multi(int packet, t_pdp_symbol *dest_template) -{ - int quality = 1; - int dst_w, dst_h, depth; - int new_packet; - unsigned int src_size; - unsigned int dst_size; - t_pdp *header0 = pdp_packet_header(packet); - t_image *image0 = pdp_packet_image_info(packet); - unsigned int src_w = image0->width; - unsigned int src_h = image0->height; - short int *src_image = (short int *)pdp_packet_data(packet); - short int *dst_image; - _pdp_description_get_dims(dest_template, &dst_w, &dst_h, &depth); - - if (depth == 0){ - depth = 1; - new_packet = pdp_packet_new_image_grey(dst_w, dst_h); - } - else { - new_packet = pdp_packet_new_image_mchp(dst_w, dst_h, depth); - } - if (-1 == new_packet) return -1; - - dst_image = (short int*)pdp_packet_data(new_packet); - - src_size = src_w*src_h; - dst_size = dst_w*dst_h; - while (depth--){ - if (quality){ - pdp_resample_scale_bilin(src_image, dst_image, src_w, src_h, dst_w, dst_h); - } - else{ - pdp_resample_scale_nn(src_image, dst_image, src_w, src_h, dst_w, dst_h); - } - src_image += src_size; - dst_image += dst_size; - } - - return new_packet; -} - -static int _pdp_packet_image_convert_fallback(int packet, t_pdp_symbol *dest_template) -{ - post("can't convert image type %s to %s", - pdp_packet_get_description(packet)->s_name, dest_template->s_name); - - return -1; -} - - - -/* the expensive factory method */ -static int pdp_image_factory(t_pdp_symbol *type) -{ - t_pdp_list *l; - t_pdp_symbol *s; - int t; - int w = 0; - int h = 0; - int d = 0; - int p = -1; - int n = 0; - int m = 0; - char *garbage = 0; - - //post("creating:"); - //post("%s", type->s_name); - - l = pdp_type_to_list(type); - s = pdp_list_pop(l).w_symbol; // first element is "image" - s = pdp_list_pop(l).w_symbol; - - /* get image type */ - if (s == pdp_gensym("grey")) t = PDP_IMAGE_GREY; - else if (s == pdp_gensym("YCrCb")) t = PDP_IMAGE_YV12; - else if (s == pdp_gensym("multi")) t = PDP_IMAGE_MCHP; - else goto exit; - - /* get image dimensions and create image */ - s = pdp_list_pop(l).w_symbol; - switch (t){ - case PDP_IMAGE_MCHP: - m = sscanf(s->s_name, "%dx%dx%d", &w, &h, &d); - p = pdp_packet_new_image_mchp(w,h,d); - break; - default: - sscanf(s->s_name, "%dx%d", &w, &h); - p = pdp_packet_new_image(t,w,h); - break; - } - if (p != -1){ - t_pdp *h = pdp_packet_header(p); - /* if type is not exact, delete the packet */ - if (type != h->desc) { - pdp_packet_delete(p); - p = -1; - } - } - exit: - pdp_list_free(l); - return p; -} - - - -void pdp_image_words_setup(t_pdp_class *c); - -void pdp_image_setup(void) -{ - t_pdp_conversion_program *program; - - /* setup the class object */ - image_class = pdp_class_new(pdp_gensym("image/*/*"), pdp_image_factory); - - /* setup image words */ - pdp_image_words_setup(image_class); - - - /* setup conversion programs */ - program = pdp_conversion_program_new(_pdp_packet_image_convert_YCrCb_to_grey, 0); - pdp_type_register_conversion(pdp_gensym("image/YCrCb/*"), pdp_gensym("image/grey/*"), program); - pdp_type_register_conversion(pdp_gensym("image/multi/*"), pdp_gensym("image/grey/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_image_convert_grey_to_YCrCb, 0); - pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("image/YCrCb/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_image_convert_grey_to_multi, 0); - pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("image/multi/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_image_convert_multi_to_YCrCb, 0); - pdp_type_register_conversion(pdp_gensym("image/multi/*"), pdp_gensym("image/YCrCb/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_image_convert_YCrCb_to_multi, 0); - pdp_type_register_conversion(pdp_gensym("image/YCrCb/*"), pdp_gensym("image/multi/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_image_convert_resample_YCrCb, 0); - pdp_type_register_conversion(pdp_gensym("image/YCrCb/*"), pdp_gensym("image/YCrCb/*"), program); - - program = pdp_conversion_program_new(_pdp_packet_image_convert_resample_multi, 0); - pdp_type_register_conversion(pdp_gensym("image/multi/*"), pdp_gensym("image/multi/*"), program); - pdp_type_register_conversion(pdp_gensym("image/grey/*"), pdp_gensym("image/grey/*"), program); - - /* catch-all fallback */ - program = pdp_conversion_program_new(_pdp_packet_image_convert_fallback, 0); - pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("image/*/*"), program); - -} diff --git a/system/type/pdp_image_words.c b/system/type/pdp_image_words.c deleted file mode 100644 index 32b6652..0000000 --- a/system/type/pdp_image_words.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Pure Data Packet system implementation. : methods for the 16 bit image packet - * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* image packet method implementation */ - - -#include "pdp.h" -#include "pdp_forth.h" - - - -// (p0, p1) -> (p0 (operator) p1) -t_pdp_word_error pdp_word_image_pp(t_pdp_stack *s, void *process_routine) -{ - int chanmask = -1; - int packet1 = -1; - int packet2 = -1; - - /* handle stack underflow */ - if (s->elements < 2) return e_underflow; - - /* get the packets from the stack */ - pdp_stack_pop_packet(s, &packet1); - pdp_stack_pop_packet(s, &packet2); - - /* ensure the destination packet is writable */ - pdp_packet_replace_with_writable(&packet1); - - /* process */ - pdp_imageproc_dispatch_2buf(process_routine, 0, chanmask, packet1, packet2); - - /* push result on stack */ - pdp_stack_push_packet(s, packet1); - - /* release the second packet */ - pdp_packet_mark_unused(packet2); - - return e_ok; -} - -t_pdp_word_error pdp_word_image_add(t_pdp_stack *s) {return pdp_word_image_pp(s, pdp_imageproc_add_process);} -t_pdp_word_error pdp_word_image_mul(t_pdp_stack *s) {return pdp_word_image_pp(s, pdp_imageproc_mul_process);} - - -/* enter a (float packet packet) -> (packet) routine */ -#define ENTER_FPP_P(f, p0, p1) \ -void *x; \ -int p0; \ -int p1; \ -float f; \ -if (s->elements < (3)) return e_underflow; \ -pdp_stack_pop_float(s, &(f)); \ -pdp_stack_pop_packet(s, &(p0)); \ -pdp_stack_pop_packet(s, &(p1)); \ -pdp_packet_replace_with_writable(&(p0)); - -/* leave a (float packet packet) -> (packet) routine */ -#define LEAVE_FPP_P(p0, p1) \ -pdp_stack_push_packet(s, p0); \ -pdp_packet_mark_unused(p1); \ -return e_ok; - - -// (f, p0, p1) -> ((1-f)*p0 + f*p1) -t_pdp_word_error pdp_word_image_mix(t_pdp_stack *s) -{ - ENTER_FPP_P(mix, p0, p1); - - /* process */ - x = pdp_imageproc_mix_new(); - pdp_imageproc_mix_setleftgain(x, 1.0f - mix); - pdp_imageproc_mix_setrightgain(x, mix); - pdp_imageproc_dispatch_2buf(&pdp_imageproc_mix_process, x, -1, p0, p1); - pdp_imageproc_mix_delete(x); - - LEAVE_FPP_P(p0, p1); -} - -// (f, p0) -> (f*p0) -t_pdp_word_error pdp_word_image_gain(t_pdp_stack *s) -{ - void *gaindata; - int chanmask = -1; - int packet = -1; - float gain = 0.5f; - - /* handle stack underflow */ - if (s->elements < 2) return e_underflow; - - /* get the packets from the stack */ - pdp_stack_pop_float(s, &gain); - pdp_stack_pop_packet(s, &packet); - - /* ensure the destination packet is writable */ - pdp_packet_replace_with_writable(&packet); - - /* process */ - gaindata = pdp_imageproc_gain_new(); - pdp_imageproc_gain_setgain(gaindata, gain); - pdp_imageproc_dispatch_1buf(&pdp_imageproc_gain_process, gaindata, chanmask, packet); - pdp_imageproc_mix_delete(gaindata); - - /* push result on stack */ - pdp_stack_push_packet(s, packet); - - return e_ok; - -} -// (f, p0) -> (f*p0) -t_pdp_word_error pdp_word_image_chanmask(t_pdp_stack *s) -{ - unsigned int chanmask = 0; - int packet = -1; - - /* handle stack underflow */ - if (s->elements < 2) return e_underflow; - - /* get the packets from the stack */ - pdp_stack_pop_int(s, &chanmask); - pdp_stack_pop_packet(s, &packet); - - /* ensure the destination packet is writable */ - pdp_packet_replace_with_writable(&packet); - - /* set channel mask */ - pdp_packet_image_set_chanmask(packet, chanmask); - - /* push result on stack */ - pdp_stack_push_packet(s, packet); - - return e_ok; - -} - -static void _add_image_primitive(char *name, int in, int out, int type_index, void *w) -{ - pdp_forthdict_add_primitive(pdp_gensym(name), w, in, out, type_index, pdp_gensym("image/*/*")); -} - - -void pdp_image_words_setup(t_pdp_class *c) -{ - /* add image specific words */ - _add_image_primitive ("add", 2, 1, 0, pdp_word_image_add); - _add_image_primitive ("mix", 3, 1, 1, pdp_word_image_mix); - _add_image_primitive ("scale", 2, 1, 1, pdp_word_image_gain); - _add_image_primitive ("mul", 2, 1, 0, pdp_word_image_mul); - _add_image_primitive ("chanmask", 2, 1, 1, pdp_word_image_chanmask); - - /* add some type oblivious words */ - pdp_forthdict_compile_word(pdp_gensym("add3"), "(add dup add)", 2, 1, -1, 0); - pdp_forthdict_compile_word(pdp_gensym("mixtest"), "(0.8 2 mov mix)", 2, 1, -1, 0); - - - /* define a processor: - - def = pdp_forth_compile_def("(inlist, outlist, setup, process)"); - */ -} diff --git a/system/type/pdp_matrix.c b/system/type/pdp_matrix.c deleted file mode 100644 index 1334864..0000000 --- a/system/type/pdp_matrix.c +++ /dev/null @@ -1,649 +0,0 @@ - -#include "pdp.h" -#include "pdp_internals.h" - -/* the class object */ -static t_pdp_class *matrix_class; - - - -/* declare header and subheader variables and exit with errval if invalid */ -#define VALID_MATRIX_HEADER(packet, header, subheader, mtype, errval) \ -t_pdp * header = pdp_packet_header( packet ); \ -t_matrix * subheader = (t_matrix *)pdp_packet_subheader( packet ); \ -if (! header ) return errval; \ -if (PDP_MATRIX != header->type) return errval; \ -if (mtype) {if (subheader->type != mtype) return errval;} - - -int pdp_packet_matrix_isvalid(int p) -{ - VALID_MATRIX_HEADER(p, h, m, 0, 0); - return 1; -} - - -void *pdp_packet_matrix_get_gsl_matrix(int p, u32 type) -{ - VALID_MATRIX_HEADER(p, h, m, type, 0); - return &m->matrix; -} - -void *pdp_packet_matrix_get_gsl_vector(int p, u32 type) -{ - VALID_MATRIX_HEADER(p, h, m, type, 0); - return &m->vector; -} - -int pdp_packet_matrix_get_type(int p) -{ - VALID_MATRIX_HEADER(p, h, m, 0, 0); - return m->type; -} - -int pdp_packet_matrix_isvector(int p) -{ - VALID_MATRIX_HEADER(p, h, m, 0, 0); - return ((m->rows == 1) || (m->columns == 1)); -} - -int pdp_packet_matrix_ismatrix(int p) -{ - VALID_MATRIX_HEADER(p, h, m, 0, 0); - return ((m->rows != 1) && (m->columns != 1)); -} - - - - -/* gsl blas matrix/vector multiplication: - -vector.vector - - (const gsl_vector * x, const gsl_vector * y, double * result) - -gsl_blas_sdot -gsl_blas_ddot -gsl_blas_cdot -gsl_blas_zdot -gsl_blas_cdotu -gsl_blas_zdotu - -matrix.vector - ( - CBLAS_TRANSPOSE_t - TransA, - double alpha, - const gsl_matrix * A, - const gsl_vector * x, - double beta, - gsl_vector * y - ) - -gsl_blas_sgemv -gsl_blas_dgemv -gsl_blas_cgemv -gsl_blas_zgemv - -matrix.matrix - ( - CBLAS_TRANSPOSE_t TransA, - CBLAS_TRANSPOSE_t TransB, - double alpha, - const gsl_matrix * A, - const gsl_matrix * B, - double beta, - gsl_matrix * C - ) - -gsl_blas_sgemm -gsl_blas_dgemm -gsl_blas_cgemm -gsl_blas_zgemm - -*/ - -/* compute the matrix inverse using the LU decomposition */ -/* it only works for double real/complex */ -int pdp_packet_matrix_LU_to_inverse(int p) -{ - int new_p; - u32 n; - int type = pdp_packet_matrix_get_type(p); - t_matrix *sheader = (t_matrix *)pdp_packet_subheader(p); - gsl_matrix *m = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(p, type); - gsl_matrix *im; - if (!m) return -1; - n = m->gsl_rows; - if (n != m->gsl_columns) return -1; - new_p = pdp_packet_new_matrix(n, n, type); - if (-1 == new_p) return -1; - im = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(new_p, type); - - switch(type){ - case PDP_MATRIX_TYPE_RDOUBLE: - gsl_linalg_LU_invert (m, &sheader->perm, im); break; - case PDP_MATRIX_TYPE_CDOUBLE: - gsl_linalg_complex_LU_invert ((gsl_matrix_complex *)m, &sheader->perm, (gsl_matrix_complex *)im); break; - default: - pdp_packet_mark_unused(new_p); - new_p = -1; - } - return new_p; -} -/* compute the LU decomposition of a square matrix */ -/* it only works for double real/complex */ -int pdp_packet_matrix_LU(int p) -{ - int p_LU, bytes; - u32 n; - int type = pdp_packet_matrix_get_type(p); - t_matrix *sh_m_LU; - t_matrix *sh_m = (t_matrix *)pdp_packet_subheader(p); - gsl_matrix *m = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(p, type); - gsl_matrix *m_LU; - if (!m) return -1; - n = m->gsl_rows; - if (n != m->gsl_columns) return -1; - p_LU = pdp_packet_new_matrix(n, n, type); - if (-1 == p_LU) return -1; - sh_m_LU = (t_matrix *)pdp_packet_subheader(p_LU); - m_LU = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(p_LU, type); - /* copy matrix data: move this to copy method */ - memcpy(pdp_packet_data(p_LU), pdp_packet_data(p), sh_m->block.size); - - switch(type){ - case PDP_MATRIX_TYPE_RDOUBLE: - gsl_linalg_LU_decomp (m_LU, &sh_m_LU->perm, &sh_m_LU->signum); break; - case PDP_MATRIX_TYPE_CDOUBLE: - gsl_linalg_complex_LU_decomp ((gsl_matrix_complex *)m_LU, &sh_m_LU->perm, &sh_m_LU->signum); break; - default: - pdp_packet_mark_unused(p_LU); - p_LU = -1; - } - return p_LU; -} - -int pdp_packet_matrix_LU_solve(int p_matrix, int p_vector) -{ - int type = pdp_packet_matrix_get_type(p_matrix); - int p_result_vector = pdp_packet_clone_rw(p_vector); - gsl_matrix *m = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(p_matrix, type); - gsl_vector *v = (gsl_vector *)pdp_packet_matrix_get_gsl_vector(p_vector, type); - gsl_vector *rv = (gsl_vector *)pdp_packet_matrix_get_gsl_vector(p_result_vector, type); - t_matrix *sh_m = (t_matrix *)pdp_packet_subheader(p_matrix); - - if (!(m && v && rv)) goto error; - - switch(type){ - case PDP_MATRIX_TYPE_RDOUBLE: - if (gsl_linalg_LU_solve (m, &sh_m->perm, v, rv)) goto error; break; - case PDP_MATRIX_TYPE_CDOUBLE: - if(gsl_linalg_complex_LU_solve ((gsl_matrix_complex*)m, &sh_m->perm, - (gsl_vector_complex *)v, (gsl_vector_complex *)rv)) goto error; break; - default: - goto error; - } - return p_result_vector; - - error: - pdp_packet_mark_unused(p_result_vector); - //post("error"); - return -1; -} - -/* matrix matrix mul: C is defining type - returns 0 on success */ -int pdp_packet_matrix_blas_mm -( - CBLAS_TRANSPOSE_t TransA, - CBLAS_TRANSPOSE_t TransB, - int pA, - int pB, - int pC, - float scale_r, - float scale_i -) -{ - gsl_complex_float cf_scale = {{scale_r, scale_i}}; - gsl_complex cd_scale = {{(double)scale_r, (double)scale_i}}; - gsl_complex_float cf_one = {{1.0f, 0.0f}}; - gsl_complex cd_one = {{1.0, 0.0}}; - gsl_matrix *mA, *mB, *mC; - int type; - type = pdp_packet_matrix_get_type(pC); - mA = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(pA,type); - mB = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(pB,type); - mC = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(pC,type); - - if (!(mA && mB)) return 1; - - - switch(type){ - case PDP_MATRIX_TYPE_RFLOAT: - return gsl_blas_sgemm(TransA, TransB, scale_r, (gsl_matrix_float *)mA, - (gsl_matrix_float *)mB, 1.0f, (gsl_matrix_float *)mC); - case PDP_MATRIX_TYPE_RDOUBLE: - return gsl_blas_dgemm(TransA, TransB, (double)scale_r, (gsl_matrix *)mA, - (gsl_matrix *)mB, 1.0, (gsl_matrix *)mC); - case PDP_MATRIX_TYPE_CFLOAT: - return gsl_blas_cgemm(TransA, TransB, cf_scale, (gsl_matrix_complex_float *)mA, - (gsl_matrix_complex_float *)mB, cf_one, (gsl_matrix_complex_float *)mC); - case PDP_MATRIX_TYPE_CDOUBLE: - return gsl_blas_zgemm(TransA, TransB, cd_scale, (gsl_matrix_complex *)mA, - (gsl_matrix_complex *)mB, cd_one, (gsl_matrix_complex *)mC); - default: - return 0; - } -} - -/* matrix vector mul: C is defining type - returns 0 on success */ -int pdp_packet_matrix_blas_mv -( - CBLAS_TRANSPOSE_t TransA, - int pA, - int pb, - int pc, - float scale_r, - float scale_i -) -{ - gsl_complex_float cf_scale = {{scale_r, scale_i}}; - gsl_complex cd_scale = {{(double)scale_r, (double)scale_i}}; - gsl_complex_float cf_one = {{1.0f, 0.0f}}; - gsl_complex cd_one = {{1.0, 0.0}}; - gsl_matrix *mA; - gsl_vector *vb, *vc; - int type; - type = pdp_packet_matrix_get_type(pA); - mA = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(pA,type); - vb = (gsl_vector *)pdp_packet_matrix_get_gsl_vector(pb,type); - vc = (gsl_vector *)pdp_packet_matrix_get_gsl_vector(pc,type); - - if (!(vb && vc)) return 1; - - - switch(type){ - case PDP_MATRIX_TYPE_RFLOAT: - return gsl_blas_sgemv(TransA, scale_r, (gsl_matrix_float *)mA, - (gsl_vector_float *)vb, 1.0f, (gsl_vector_float *)vc); - case PDP_MATRIX_TYPE_RDOUBLE: - return gsl_blas_dgemv(TransA, (double)scale_r, (gsl_matrix *)mA, - (gsl_vector *)vb, 1.0, (gsl_vector *)vc); - case PDP_MATRIX_TYPE_CFLOAT: - return gsl_blas_cgemv(TransA, cf_scale, (gsl_matrix_complex_float *)mA, - (gsl_vector_complex_float *)vb, cf_one, (gsl_vector_complex_float *)vc); - case PDP_MATRIX_TYPE_CDOUBLE: - return gsl_blas_zgemv(TransA, cd_scale, (gsl_matrix_complex *)mA, - (gsl_vector_complex *)vb, cd_one, (gsl_vector_complex *)vc); - default: - return 0; - } -} - - - -t_pdp_symbol *_pdp_matrix_get_description(t_pdp *header) -{ - t_matrix *m = (t_matrix *)(&header->info.raw); - char description[100]; - char *c = description; - int encoding; - - if (!header) return pdp_gensym("invalid"); - else if (!header->desc){ - /* if description is not defined, try to reconstruct it (for backwards compat) */ - if (header->type == PDP_MATRIX){ - - c += sprintf(c, "matrix"); - - switch(m->type){ - case PDP_MATRIX_TYPE_RFLOAT: c += sprintf(c, "/float/real"); break; - case PDP_MATRIX_TYPE_CFLOAT: c += sprintf(c, "/float/complex"); break; - case PDP_MATRIX_TYPE_RDOUBLE: c += sprintf(c, "/double/real"); break; - case PDP_MATRIX_TYPE_CDOUBLE: c += sprintf(c, "/double/complex"); break; - default: - c += sprintf(c, "/unknown"); goto exit; - } - - c += sprintf(c, "/%dx%d", (int)m->rows, (int)m->columns); - - exit: - return pdp_gensym(description); - } - else return pdp_gensym("unknown"); - } - else return header->desc; -} - - - -static void _pdp_matrix_copy(t_pdp *dst, t_pdp *src); -static void _pdp_matrix_clone(t_pdp *dst, t_pdp *src); -static void _pdp_matrix_reinit(t_pdp *dst); -static void _pdp_matrix_cleanup(t_pdp *dst); - -static size_t _pdp_matrix_mdata_byte_size(u32 rows, u32 columns, u32 type) -{ - size_t dsize = rows * columns; - switch (type){ - case PDP_MATRIX_TYPE_RFLOAT: dsize *= sizeof(float); break; - case PDP_MATRIX_TYPE_CFLOAT: dsize *= 2*sizeof(float); break; - case PDP_MATRIX_TYPE_RDOUBLE: dsize *= sizeof(double); break; - case PDP_MATRIX_TYPE_CDOUBLE: dsize *= 2*sizeof(double); break; - default: dsize = 0; - } - return dsize; -} - - -static size_t _pdp_matrix_pdata_vector_size(u32 rows, u32 columns) -{ - return (rows>columns ? rows : columns); -} - - -static void _pdp_matrix_init(t_pdp *dst, u32 rows, u32 columns, u32 type) -{ - int i; - t_matrix *m = (t_matrix *)(&dst->info.raw); - void *d = ((void *)dst) + PDP_HEADER_SIZE; - int matrix_bytesize = _pdp_matrix_mdata_byte_size(rows, columns, type); - int permsize = _pdp_matrix_pdata_vector_size(rows, columns); - - /* set meta data */ - m->type = type; - m->rows = rows; - m->columns = columns; - - /* set the block data */ - m->block.size = matrix_bytesize; - m->block.data = (double *)d; - - /* set the vector view */ - m->vector.size = (1==columns) ? rows : columns; - m->vector.stride = 1; - m->vector.data = (double *)d; - m->vector.block = &m->block; - m->vector.owner = 0; - - /* set the matrix view */ - m->matrix.gsl_rows = rows; - m->matrix.gsl_columns = columns; - m->matrix.tda = columns; - m->matrix.data = (double *)d; - m->matrix.block = &m->block; - m->matrix.owner = 0; - - /* set the permutation object & init */ - m->perm.size = permsize; - m->perm.data = (size_t *)(d + matrix_bytesize); - for(i=0; i<permsize; i++) m->perm.data[i] = i; - m->signum = -1; - - /* init packet header */ - dst->theclass = matrix_class; - dst->desc = _pdp_matrix_get_description(dst); - -} - -static void _pdp_matrix_clone(t_pdp *dst, t_pdp *src) -{ - t_matrix *m = (t_matrix *)(&src->info.raw); - _pdp_matrix_init(dst, m->rows, m->columns, m->type); - -} -static void _pdp_matrix_copy(t_pdp *dst, t_pdp *src) -{ - _pdp_matrix_clone(dst, src); - memcpy(dst + PDP_HEADER_SIZE, src + PDP_HEADER_SIZE, src->size - PDP_HEADER_SIZE); - //post("matrix copy successful"); -} -static void _pdp_matrix_reinit(t_pdp *dst) -{ - /* nothing to do, assuming data is correct */ -} -static void _pdp_matrix_cleanup(t_pdp *dst) -{ - /* no extra memory to free */ -} - -int pdp_packet_new_matrix(u32 rows, u32 columns, u32 type) -{ - t_pdp *header; - int dsize, p; - - /* compute the blocksize for the matrix data */ - /* if 0, something went wrong -> return invalid packet */ - if (!(dsize = _pdp_matrix_mdata_byte_size(rows, columns, type))) return -1; - dsize += sizeof(size_t) * _pdp_matrix_pdata_vector_size(rows, columns); - - p = pdp_packet_new(PDP_MATRIX, dsize); - if (-1 == p) return -1; - header = pdp_packet_header(p); - - _pdp_matrix_init(header, rows, columns, type); - - return p; -} - -int pdp_packet_new_matrix_product_result(CBLAS_TRANSPOSE_t TransA, CBLAS_TRANSPOSE_t TransB, int pA, int pB) -{ - gsl_matrix *mA, *mB; - u32 type = pdp_packet_matrix_get_type(pA); - - u32 colA, colB, rowA, rowB; - - /* check if A is a matrix */ - if (!type) return -1; - - mA = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(pA, type); - mB = (gsl_matrix *)pdp_packet_matrix_get_gsl_matrix(pB, type); - - /* check if A and B are same type */ - if (!mB) return -1; - - /* get dims A */ - if (TransA == CblasNoTrans){ - rowA = mA->gsl_rows; - colA = mA->gsl_columns; - } - else { - rowA = mA->gsl_columns; - colA = mA->gsl_rows; - } - - /* get dims B */ - if (TransB == CblasNoTrans){ - rowB = mB->gsl_rows; - colB = mB->gsl_columns; - } - else { - rowB = mB->gsl_columns; - colB = mB->gsl_rows; - } - - /* check if sizes are compatible */ - if (colA != rowB) return -1; - - /* create new packet */ - return pdp_packet_new_matrix(rowA, colB, type); -} - -void pdp_packet_matrix_setzero(int p) -{ - t_matrix *m; - if (!pdp_packet_matrix_isvalid(p)) return; - m = (t_matrix *) pdp_packet_subheader(p); - memset(m->block.data, 0, m->block.size); -} - - - -/* type conversion programs */ -static int _pdp_packet_convert_matrix_to_greyimage(int packet, t_pdp_symbol *dest_template) -{ - t_pdp *header = pdp_packet_header(packet); - t_matrix *matrix = (t_matrix *)pdp_packet_subheader(packet); - void *data = pdp_packet_data(packet); - s16 *new_data; - u32 c,r, nbelements; - int new_p; - u32 i; - - c = matrix->columns; - r = matrix->rows; - nbelements = c*r; - - new_p = pdp_packet_new_image_grey(c,r); - if (-1 == new_p) return -1; - new_data = (s16 *)pdp_packet_data(new_p); - - /* convert first channel */ - switch(matrix->type){ - case PDP_MATRIX_TYPE_RFLOAT: - for (i=0; i<nbelements; i++) (new_data)[i] = (s16)(((float *)data)[i] * (float)0x8000); break; - case PDP_MATRIX_TYPE_CFLOAT: //only copy real channel - for (i=0; i<nbelements; i++) (new_data)[i] = (s16)(((float *)data)[i<<1] * (float)0x8000); break; - case PDP_MATRIX_TYPE_RDOUBLE: - for (i=0; i<nbelements; i++) (new_data)[i] = (s16)(((double *)data)[i] * (float)0x8000); break; - case PDP_MATRIX_TYPE_CDOUBLE: //only copy real channel - for (i=0; i<nbelements; i++) (new_data)[i] = (s16)(((double *)data)[i<<1] * (float)0x8000); break; - default: - pdp_packet_mark_unused(new_p); - new_p = -1; - } - return new_p; -} - -static int _pdp_packet_convert_image_to_matrix(int packet, t_pdp_symbol *dest_template, int type) -{ - t_pdp *header = pdp_packet_header(packet); - t_image *image = pdp_packet_image_info(packet); - s16 *data = (s16 *)pdp_packet_data(packet); - void *new_data; - u32 w,h, nbelements; - int new_p; - int encoding = image->encoding; - u32 i; - - if (!pdp_packet_image_isvalid(packet)) return -1; - w = image->width; - h = image->height; - nbelements = w*h; - - new_p = pdp_packet_new_matrix(h,w, type); - if (-1 == new_p) return -1; - new_data = pdp_packet_data(new_p); - - switch (encoding){ - case PDP_IMAGE_YV12: - case PDP_IMAGE_GREY: - case PDP_IMAGE_MCHP: - /* convert first channel */ - switch(type){ - case PDP_MATRIX_TYPE_RFLOAT: - for (i=0; i<nbelements; i++) - ((float *)new_data)[i] = ((float)data[i]) * (1.0f / (float)0x8000); break; - case PDP_MATRIX_TYPE_RDOUBLE: - for (i=0; i<nbelements; i++) - ((double *)new_data)[i] = ((double)data[i]) * (1.0f / (double)0x8000); break; - case PDP_MATRIX_TYPE_CFLOAT: - for (i=0; i<nbelements; i++){ - ((float *)new_data)[i*2] = ((float)data[i]) * (1.0f / (float)0x8000); - ((float *)new_data)[i*2+1] = 0.0f; - } - break; - case PDP_MATRIX_TYPE_CDOUBLE: - for (i=0; i<nbelements; i++){ - ((double *)new_data)[i*2] = ((double)data[i]) * (1.0f / (double)0x8000); - ((double *)new_data)[i*2+1] = 0.0; - } - break; - default: - post("_pdp_packet_convert_image_to_matrix: INTERNAL ERROR"); - } - break; - default: - pdp_packet_mark_unused(new_p); - new_p = -1; - break; - } - - return new_p; - -} - -static int _pdp_packet_convert_image_to_floatmatrix(int packet, t_pdp_symbol *dest_template){ - return _pdp_packet_convert_image_to_matrix(packet, dest_template, PDP_MATRIX_TYPE_RFLOAT);} -static int _pdp_packet_convert_image_to_doublematrix(int packet, t_pdp_symbol *dest_template){ - return _pdp_packet_convert_image_to_matrix(packet, dest_template, PDP_MATRIX_TYPE_RDOUBLE);} -static int _pdp_packet_convert_image_to_complexfloatmatrix(int packet, t_pdp_symbol *dest_template){ - return _pdp_packet_convert_image_to_matrix(packet, dest_template, PDP_MATRIX_TYPE_CFLOAT);} -static int _pdp_packet_convert_image_to_complexdoublematrix(int packet, t_pdp_symbol *dest_template){ - return _pdp_packet_convert_image_to_matrix(packet, dest_template, PDP_MATRIX_TYPE_CDOUBLE);} - - -static int _pdp_packet_matrix_convert_fallback(int packet, t_pdp_symbol *dest_template) -{ - post("can't convert image type %s to %s", - pdp_packet_get_description(packet)->s_name, dest_template->s_name); - - return -1; -} - - -/* this seems like a nice spot to place a dummy gsl signal handler */ -static void _gsl_error_handler (const char * reason, - const char * file, - int line, - int gsl_errno) -{ - //post("gsl error:\nREASON: %s\nFILE:%s\nLINE:%d\nERRNO:%d", reason, file, line, gsl_errno); -} - -static int pdp_matrix_factory(t_pdp_symbol *type) -{ - return -1; -} -void pdp_matrix_setup(void) -{ - t_pdp_conversion_program *program; - - - /* setup the class */ - matrix_class = pdp_class_new(pdp_gensym("matrix/*/*/*"), pdp_matrix_factory); - matrix_class->copy = _pdp_matrix_copy; - matrix_class->clone = _pdp_matrix_clone; - matrix_class->reinit = _pdp_matrix_reinit; - matrix_class->cleanup = _pdp_matrix_cleanup; - - - /* image -> matrix: default = double/real (most ops available) */ - program = pdp_conversion_program_new(_pdp_packet_convert_image_to_doublematrix, 0); - pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("matrix/double/real/*"), program); - program = pdp_conversion_program_new(_pdp_packet_convert_image_to_floatmatrix, 0); - pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("matrix/float/real/*"), program); - program = pdp_conversion_program_new(_pdp_packet_convert_image_to_complexdoublematrix, 0); - pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("matrix/double/complex/*"), program); - program = pdp_conversion_program_new(_pdp_packet_convert_image_to_complexfloatmatrix, 0); - pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("matrix/float/complex/*"), program); - - /* matrix -> image */ - program = pdp_conversion_program_new(_pdp_packet_convert_matrix_to_greyimage, 0); - pdp_type_register_conversion(pdp_gensym("matrix/*/*/*"), pdp_gensym("image/grey/*"), program); - - /* fallbacks */ - program = pdp_conversion_program_new(_pdp_packet_matrix_convert_fallback, 0); - pdp_type_register_conversion(pdp_gensym("matrix/*/*/*"), pdp_gensym("image/*/*"), program); - pdp_type_register_conversion(pdp_gensym("matrix/*/*/*"), pdp_gensym("bitmap/*/*"), program); - pdp_type_register_conversion(pdp_gensym("image/*/*"), pdp_gensym("matrix/*/*/*/*"), program); - pdp_type_register_conversion(pdp_gensym("bitmap/*/*"), pdp_gensym("matrix/*/*/*/*"), program); - - /* setup gsl handler */ - if(gsl_set_error_handler(_gsl_error_handler)){ - post("pdp_matrix_setup: WARNING: overriding gsl error handler."); - } - -} |