void bench_plot1(int n, epx_pixel_t (*src_unpack)(u_int8_t*), void (*dst_pack)(epx_pixel_t, u_int8_t*)) { epx_pixmap_t* a; epx_gc_t* gc; int j; double tfsum = 0.0; u_int8_t* src_ptr; unsigned int bytesPerRow; unsigned int bytesPerPixel; int x, y; /* Bench mark fill function */ gc = epx_gc_create(); a = epx_pixmap_create(640, 480, EPX_FORMAT_ARGB); epx_gc_set_fill_style(gc, EPX_FILL_STYLE_SOLID); epx_gc_set_border_width(gc, 0); epx_gc_set_fill_color(gc, epx_pixel_red); bytesPerRow = a->bytes_per_row; bytesPerPixel = a->bytes_per_pixel; for (j = 0; j < n; j++) { struct timeval t, t0, t1; double tf; gettimeofday(&t0, NULL); src_ptr = EPX_PIXEL_ADDR(a, 0, 0); for (y = 0; y < 480; y++) { u_int8_t* src1 = src_ptr; for (x = 0; x < 640; x++) { epx_pixel_t p; p = src_unpack(src1); p.a = 100; p.r = 1; p.g = 1; p.b = 1; dst_pack(p, src1); src1 += bytesPerPixel; } src_ptr += bytesPerRow; } gettimeofday(&t1, NULL); timersub(&t1, &t0, &t); tf = 100.0/(t.tv_sec+(t.tv_usec/1000000.0)); tfsum += tf; } printf("PLOT1 Avg: %f/s\n", tfsum/n); }
// // useAlpha=false make alpha channel opaque // useAlpha=true use alpha value as is // useClient=true make use of client stored data, assume texture data // survive the rendering phase. // wrap=GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, // GL_REPEAT or GL_MIRRORED_REPEAT // // Load textures formats: // 1 - ARB_texture_non_power_of_two // 2 - ARB_texture_rectangle (used if non normalized is request) // 3 - GL_TEXTURE_2D (possibly scaled otherwise) // // int epx_gl_load_texture(epx_pixmap_t* pic, GLuint* textureName, int useAlpha, int useClient, GLuint wrap, int src_x, int src_y, unsigned int width,unsigned int height) { GLint tx_iformat; GLenum tx_format; GLenum tx_type; float saveScale; float saveBias; GLenum target; int normalized = 1; epx_pixmap_t* pic2 = NULL; switch(pic->pixel_format) { case EPX_FORMAT_R8G8B8: tx_iformat = GL_RGB8; tx_format = GL_RGB; tx_type = GL_UNSIGNED_BYTE; break; case EPX_FORMAT_565_BE: tx_iformat = GL_RGB5; tx_format = GL_RGB; #if BYTE_ORDER == BIG_ENDIAN tx_type = GL_UNSIGNED_SHORT_5_6_5; #else tx_type = GL_UNSIGNED_SHORT_5_6_5_REV; #endif break; case EPX_FORMAT_565_LE: tx_iformat = GL_RGB5; tx_format = GL_RGB; #if BYTE_ORDER == BIG_ENDIAN tx_type = GL_UNSIGNED_SHORT_5_6_5_REV; #else tx_type = GL_UNSIGNED_SHORT_5_6_5; #endif break; case EPX_FORMAT_B8G8R8: tx_iformat = GL_RGB8; tx_format = GL_BGR; tx_type = GL_UNSIGNED_BYTE; break; case EPX_FORMAT_A8R8G8B8: tx_iformat = GL_RGBA8; tx_format = GL_BGRA_EXT; #if BYTE_ORDER == BIG_ENDIAN tx_type = GL_UNSIGNED_INT_8_8_8_8_REV; #else tx_type = GL_UNSIGNED_INT_8_8_8_8; #endif break; case EPX_FORMAT_R8G8B8A8: tx_iformat = GL_RGBA8; tx_format = GL_RGBA; #if BYTE_ORDER == BIG_ENDIAN tx_type = GL_UNSIGNED_INT_8_8_8_8; #else tx_type = GL_UNSIGNED_INT_8_8_8_8_REV; #endif break; case EPX_FORMAT_B8G8R8A8: tx_iformat = GL_RGBA8; tx_format = GL_BGRA; #if BYTE_ORDER == BIG_ENDIAN tx_type = GL_UNSIGNED_INT_8_8_8_8; #else tx_type = GL_UNSIGNED_INT_8_8_8_8_REV; #endif break; default: return -1; // Better error code? } if (*textureName == 0) glGenTextures(1, textureName); /* FIXME check extensions better */ if (normalized) { #ifndef GL_ARB_texture_non_power_of_two unsigned int width2 = nearest_pow2(width); unsigned int height2 = nearest_pow2(height); printf("POT: width2=%d, height2=%d\n", width2, height2); if ((width2==0) || (height2==0)) return -1; if ((width2 != width) || (height2 != height)) { epx_pixmap_t* pic2 = epx_pixmap_create(width2, height2, pic->pixel_format); printf("POT: scale image\n"); gluScaleImage(tx_format, width, height, tx_type, EPX_PIXEL_ADDR(pic,src_x,src_y), width2, height2, tx_type, EPX_PIXEL_ADDR(pic2,0,0)); width = width2; height = height2; pic = pic2; } #endif target = GL_TEXTURE_2D; } else { #ifdef GL_ARB_texture_rectangle target = GL_TEXTURE_RECTANGLE_ARB; #endif } glBindTexture (target, *textureName); glTexParameteri(target,GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(target,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(target,GL_TEXTURE_WRAP_S, wrap); glTexParameteri(target,GL_TEXTURE_WRAP_T, wrap); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glPixelStorei (GL_UNPACK_ROW_LENGTH, pic->bytes_per_row/pic->bytes_per_pixel); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); #ifdef GL_UNPACK_CLIENT_STORAGE_APPLE if (useClient) // This speeds processing up from 40-50 => 50-60 fps :-) // BUT WE MUST PRESERVE THE PIXELS until next reload!!!!!! // this is what useClient is for glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); #endif if (!useAlpha) { // Do not use possibly bad alpha value glGetFloatv(GL_ALPHA_SCALE, &saveScale); glGetFloatv(GL_ALPHA_BIAS, &saveBias); glPixelTransferf(GL_ALPHA_SCALE, 0.0); glPixelTransferf(GL_ALPHA_BIAS, 1.0); } // FIXME Update with: // glTexSubImage2D(target, 0, 0, 0, width, height, tx_format, tx_type, // EPIXEL_ADDR(pic, src_x, src_y)) // but only if width & height is same as original texture glTexImage2D (target, 0, tx_iformat, width, height, 0, tx_format, tx_type, EPX_PIXEL_ADDR(pic, src_x, src_y)); if (!useAlpha) { // Reset saved values glPixelTransferf(GL_ALPHA_SCALE, saveScale); glPixelTransferf(GL_ALPHA_BIAS, saveBias); } if (pic2) epx_pixmap_destroy(pic2); return 0; }
/* Copy animation frame to background */ void epx_anim_copy_frame(epx_pixmap_t* pic, epx_gc_t* gc, int x, int y, int width, int height, epx_format_t src_pt, epx_anim_pixels_t* base, epx_anim_pixels_t* current) { (void) gc; u_int8_t *src = (u_int8_t*) current; u_int8_t* src_save = NULL; int n_blocks = 0; unsigned char *dst0 = EPX_PIXEL_ADDR(pic, x, y); int dst_wb = pic->bytes_per_row; epx_format_t src_format = src_pt; int srcPixelSize = EPX_PIXEL_BYTE_SIZE(src_pt); epx_format_t dst_format = pic->pixel_format; int dstPixelSize = pic->bytes_per_pixel; while(height--) { unsigned char* dst = dst0; int w = width; dst0 += dst_wb; while(w) { epx_anim_pixels_t* hdr = (epx_anim_pixels_t*) src; u_int32_t pcount; if (hdr->type == EPX_ANIM_INDIRECT) { u_int8_t *isrc = ((u_int8_t*)base) + hdr->count; n_blocks = hdr->nblocks; // number of blocks to run src_save = src + sizeof(epx_anim_pixels_t); // continue point src = isrc; hdr = (epx_anim_pixels_t*) src; // switch to indirect header } src += sizeof(epx_anim_pixels_t); pcount = hdr->count; w -= pcount; switch(hdr->type) { case EPX_ANIM_SKIP: break; case EPX_ANIM_SHADOW: epx_copy_row(src, EPX_FORMAT_A8, dst, dst_format, pcount); src += pcount; break; case EPX_ANIM_RGBA: epx_copy_row(src,EPX_FORMAT_RGBA, dst, dst_format, pcount); src += pcount*4; break; case EPX_ANIM_BGRA: epx_copy_row(src,EPX_FORMAT_BGRA, dst, dst_format, pcount); src += pcount*4; break; case EPX_ANIM_COPY: // BGRA values!!! epx_copy_row(src, src_format, dst, dst_format, pcount); src += pcount*srcPixelSize; break; case EPX_ANIM_FILL: epx_fill_row(dst, dst_format, epx_pixel_argb(src[0],src[1],src[2],src[3]), pcount); src += 4; break; default: break; } dst += pcount*dstPixelSize; if (n_blocks) { // are we running indirect blocks? if (n_blocks == 1) src = src_save; // restore & continue n_blocks--; } } } }
/* Draw & Blend animation frame with background */ void epx_anim_draw_frame(epx_pixmap_t* pic, epx_gc_t* gc, int x, int y, int width, int height, epx_format_t src_pt, epx_anim_pixels_t* base, epx_anim_pixels_t* current) { u_int8_t fader = gc->fader_value; u_int8_t *src = (u_int8_t*) current; u_int8_t* src_save = NULL; int n_blocks = 0; unsigned char *dst0 = EPX_PIXEL_ADDR(pic, x, y); int dst_wb = pic->bytes_per_row; epx_format_t src_format = src_pt; int srcPixelSize = EPX_PIXEL_BYTE_SIZE(src_pt); epx_format_t dst_format = pic->pixel_format; int dstPixelSize = pic->bytes_per_pixel; epx_rect_t r = {{x,y}, {width,height}}; int x0, yi; int clip_y0, clip_y1; int clip_x0, clip_x1, clip_len; int need_x_clip; if (epx_rect_is_subrect(&r, &pic->clip)) { if (src_format == dst_format) { if (dst_format == EPX_FORMAT_BGRA) goto bgra_noclip; else if (dst_format == EPX_FORMAT_RGBA) goto rgba_noclip; goto no_clip; } } goto clip; /* if we must clip the image we do the general stuff */ clip: clip_y0 = epx_rect_top(&pic->clip); clip_y1 = epx_rect_bottom(&pic->clip); clip_x0 = epx_rect_left(&pic->clip); clip_x1 = epx_rect_right(&pic->clip); clip_len = epx_rect_width(&pic->clip); yi = y; x0 = x; need_x_clip = !( (x0 >= clip_x0) && ((x0+width-1) <= clip_x1) ); while(height--) { int xi = x0; int w = width; if (!epx_in_range(yi, clip_y0, clip_y1)) { // The line is clipped but we must skip the source data while(w) { epx_anim_pixels_t* hdr = (epx_anim_pixels_t*) src; u_int32_t pcount; if (hdr->type == EPX_ANIM_INDIRECT) { u_int8_t *isrc = ((u_int8_t*)base) + hdr->count; n_blocks = hdr->nblocks; // number of blocks to run src_save = src + sizeof(epx_anim_pixels_t); // continue point src = isrc; hdr = (epx_anim_pixels_t*) src; // switch to indirect header } src += sizeof(epx_anim_pixels_t); pcount = hdr->count; w -= pcount; switch(hdr->type) { case EPX_ANIM_SKIP: break; case EPX_ANIM_SHADOW: src += pcount; break; case EPX_ANIM_BGRA: case EPX_ANIM_RGBA: src += pcount*4; break; case EPX_ANIM_COPY: src += pcount*srcPixelSize; break; case EPX_ANIM_FILL: src += 4; break; default: break; } if (n_blocks) { // are we running indirect blocks? if (n_blocks == 1) src = src_save; // restore & continue n_blocks--; } } } else if (!need_x_clip) { // No horizontal clipping needed unsigned char *dst = EPX_PIXEL_ADDR(pic, xi, yi); while(w) { epx_anim_pixels_t* hdr = (epx_anim_pixels_t*) src; u_int32_t pcount; u_int8_t a; if (hdr->type == EPX_ANIM_INDIRECT) { u_int8_t *isrc = ((u_int8_t*)base) + hdr->count; n_blocks = hdr->nblocks; // number of blocks to run src_save = src + sizeof(epx_anim_pixels_t); // continue point src = isrc; hdr = (epx_anim_pixels_t*) src; // switch to indirect header } src += sizeof(epx_anim_pixels_t); pcount = hdr->count; w -= pcount; switch(hdr->type) { case EPX_ANIM_SKIP: break; case EPX_ANIM_SHADOW: epx_add_color_row(src, EPX_FORMAT_A8, dst, dst_format, fader, epx_pixel_transparent, pcount, EPX_FLAG_BLEND); src += pcount; break; case EPX_ANIM_BGRA: epx_fade_row(src,EPX_FORMAT_BGRA, dst, dst_format, fader, pcount); src += pcount*4; break; case EPX_ANIM_RGBA: epx_fade_row(src,EPX_FORMAT_RGBA, dst, dst_format, fader, pcount); src += pcount*4; break; case EPX_ANIM_COPY: if (fader == ALPHA_FACTOR_1) epx_copy_row(src, src_format, dst, dst_format, pcount); else if (fader != ALPHA_FACTOR_0) epx_alpha_row(src, src_format, dst, dst_format, fader, pcount); src += pcount*srcPixelSize; break; case EPX_ANIM_FILL: a= (fader==ALPHA_FACTOR_1) ? src[0] : ((src[0]*fader) >> 8); if (a == EPX_ALPHA_TRANSPARENT) ; else if (a == EPX_ALPHA_OPAQUE) epx_fill_row(dst, dst_format, epx_pixel_argb(a,src[1],src[2],src[3]), pcount); else epx_fill_row_blend(dst, dst_format, epx_pixel_argb(a,src[1], src[2],src[3]), pcount); src += 4; break; default: break; } dst += pcount*dstPixelSize; if (n_blocks) { // are we running indirect blocks? if (n_blocks == 1) src = src_save; // restore & continue n_blocks--; } } } else { // we need to clip dds
default: break; } dst += pcount*dstPixelSize; if (n_blocks) { // are we running indirect blocks? if (n_blocks == 1) src = src_save; // restore & continue n_blocks--; } } } else { // we need to clip dds unsigned char *dst = EPX_PIXEL_ADDR(pic, xi, yi); while(w) { epx_anim_pixels_t* hdr = (epx_anim_pixels_t*) src; u_int32_t pcount; u_int8_t a; if (hdr->type == EPX_ANIM_INDIRECT) { u_int8_t *isrc = ((u_int8_t*)base) + hdr->count; n_blocks = hdr->nblocks; // number of blocks to run src_save = src + sizeof(epx_anim_pixels_t); // continue point src = isrc; hdr = (epx_anim_pixels_t*) src; // switch to indirect header } src += sizeof(epx_anim_pixels_t);