From: Josh V. <ho...@na...> - 2001-03-08 19:24:34
|
Keith Whitwell <ke...@va...> writes: > You may want to avoid sharing the nv-specific stuff, but any progress on otf > codegen has lots of application beyond that extension -- I can think of a > dozen uses for something like this. What would you guys think of putting stuff like this in Mesa? #include <dlfcn.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> void * compile_function(const char *name, const char *source, void **r_handle) { char name_c[256], name_so[256], cmdline[768]; FILE *fp; size_t len = strlen(source); pid_t pid = getpid(); void *handle, *sym; sprintf(name_c, "/tmp/%ld_%.200s.c", (long)pid, name); sprintf(name_so, "/tmp/%ld_%.200s.so", (long)pid, name); fp = fopen(name_c, "w"); if (fp == NULL) return NULL; if (fwrite(source, len, 1, fp) != 1) { fclose(fp); remove(name_c); return NULL; } fclose(fp); sprintf(cmdline, "gcc -O2 -fomit-frame-pointer -shared %s -o %s", name_c, name_so); if (system(cmdline) != 0) { remove(name_c); return NULL; } remove(name_c); handle = dlopen(name_so, RTLD_NOW); remove(name_so); if (handle == NULL) return NULL; sym = dlsym(handle, name); if (sym == NULL) { dlclose(handle); return NULL; } *r_handle = handle; return sym; } void free_function(void *handle) { dlclose(handle); } static const char *convert_template = " void NAME(void *vsrc, void *vdst, int count) { SRC_TYPE *src = vsrc; DST_TYPE *dst = vdst; int i; unsigned int s, d, r, g, b, a; for (i = 0; i < count; i++) { s = src[i]; r = s >> SRC_RPOS; r &= (1 << SRC_RSZ) - 1; #if SRC_RSZ < DST_RSZ r = r * ((1 << DST_RSZ) - 1) / ((1 << SRC_RSZ - 1)); #else r >>= SRC_RSZ - DST_RSZ; #endif r <<= DST_RPOS; g = s >> SRC_GPOS; g &= (1 << SRC_GSZ) - 1; #if SRC_GSZ < DST_GSZ g = g * ((1 << DST_GSZ) - 1) / ((1 << SRC_GSZ - 1)); #else g >>= SRC_GSZ - DST_GSZ; #endif g <<= DST_GPOS; b = s >> SRC_BPOS; b &= (1 << SRC_BSZ) - 1; #if SRC_BSZ < DST_BSZ b = b * ((1 << DST_BSZ) - 1) / ((1 << SRC_BSZ - 1)); #else b >>= SRC_BSZ - DST_BSZ; #endif b <<= DST_BPOS; a = s >> SRC_APOS; a &= (1 << SRC_ASZ) - 1; #if SRC_ASZ < DST_ASZ a = a * ((1 << DST_ASZ) - 1) / ((1 << SRC_ASZ - 1)); #else a >>= SRC_ASZ - DST_ASZ; #endif a <<= DST_APOS; d = r | g | b | a; dst[i] = d; } } "; int convert_pixels(void *src, int src_pixel_size, int src_rpos, int src_gpos, int src_bpos, int src_apos, int src_rsz, int src_gsz, int src_bsz, int src_asz, void *dst, int dst_pixel_size, int dst_rpos, int dst_gpos, int dst_bpos, int dst_apos, int dst_rsz, int dst_gsz, int dst_bsz, int dst_asz, int count) { char buf[10000], name[200]; char *p = buf; void (*fn)(void *src, void *dst, int count); void *handle; switch (dst_pixel_size) { case 1: case 2: case 4: break; default: return 0; } sprintf(name, "convert_%d%d%d%d_%d%d%d%d", src_rsz, src_gsz, src_bsz, src_asz, dst_rsz, dst_gsz, dst_bsz, dst_asz); p += sprintf(p, "#define NAME %s\n", name); p += sprintf(p, "#define SRC_TYPE "); switch (src_pixel_size) { case 1: p += sprintf(p, "unsigned char\n"); break; case 2: p += sprintf(p, "unsigned short\n"); break; case 4: p += sprintf(p, "unsigned int\n"); break; default: return 0; } p += sprintf(p, "#define SRC_RPOS %d\n", src_rpos); p += sprintf(p, "#define SRC_GPOS %d\n", src_gpos); p += sprintf(p, "#define SRC_BPOS %d\n", src_bpos); p += sprintf(p, "#define SRC_APOS %d\n", src_apos); p += sprintf(p, "#define SRC_RSZ %d\n", src_rsz); p += sprintf(p, "#define SRC_GSZ %d\n", src_gsz); p += sprintf(p, "#define SRC_BSZ %d\n", src_bsz); p += sprintf(p, "#define SRC_ASZ %d\n", src_asz); p += sprintf(p, "#define DST_TYPE "); switch (dst_pixel_size) { case 1: p += sprintf(p, "unsigned char\n"); break; case 2: p += sprintf(p, "unsigned short\n"); break; case 4: p += sprintf(p, "unsigned int\n"); break; default: return 0; } p += sprintf(p, "#define DST_RPOS %d\n", dst_rpos); p += sprintf(p, "#define DST_GPOS %d\n", dst_gpos); p += sprintf(p, "#define DST_BPOS %d\n", dst_bpos); p += sprintf(p, "#define DST_APOS %d\n", dst_apos); p += sprintf(p, "#define DST_RSZ %d\n", dst_rsz); p += sprintf(p, "#define DST_GSZ %d\n", dst_gsz); p += sprintf(p, "#define DST_BSZ %d\n", dst_bsz); p += sprintf(p, "#define DST_ASZ %d\n", dst_asz); strcpy(p, convert_template); fn = compile_function(name, buf, &handle); if (fn != NULL) fn(src, dst, count); else return 0; free_function(handle); return 1; } int main(void) { unsigned int src[8] = { 0xff555555, 0x55ff5555, 0x5555ff55, 0x555555ff, 0x00555555, 0x55005555, 0x55550055, 0x55555500 }; unsigned short dst[8]; int i; i = convert_pixels( src, 4, /* pixel size */ 16, 8, 0, 24, /* offsets for r, g, b, a */ 8, 8, 8, 8, /* sizes for r, g, b, a */ dst, 2, 8, 4, 0, 12, 4, 4, 4, 4, 8); /* count */ if (i == 0) return 1; for (i = 0; i < 8; i++) printf("%08x %04x\n", src[i], dst[i]); return 0; } |