/* Perform a stretch blit between two surfaces of the same format. NOTE: This function is not safe to call from multiple threads! */ int egl_soft_stretch(uint8_t* src, int s_x, int s_y, int s_w, int s_h, uint8_t* dst, int d_x, int d_y, int d_w, int d_h, int bpp) { int src_locked; int dst_locked; int pos, inc; int dst_maxrow; int src_row, dst_row; uint8_t *srcp = NULL; uint8_t *dstp; /* Set up the data... */ pos = 0x10000; inc = (s_h << 16) / d_h; src_row = s_y; dst_row = d_y; /* Perform the stretch blit */ for (dst_maxrow = dst_row + d_h; dst_row < dst_maxrow; ++dst_row) { dstp = (uint8_t *) dst + (dst_row * d_w) + (d_x * bpp); while (pos >= 0x10000L) { srcp = (uint8_t *) src + (src_row * s_w) + (s_x * bpp); ++src_row; pos -= 0x10000L; } switch (bpp) { case 1: copy_row1(srcp, s_w, dstp, d_w); break; case 2: copy_row2((uint16_t *) srcp, s_w, (uint16_t *) dstp, d_w); break; case 3: copy_row3(srcp, s_w, dstp, d_w); break; case 4: copy_row4((uint32_t *) srcp, s_w, (uint32_t *) dstp, d_w); break; } pos += inc; } return 1; }
/* Perform a stretch blit between two surfaces of the same format. NOTE: This function is not safe to call from multiple threads! */ int SDL_SoftStretch(SDL_Surface * src, const SDL_Rect * srcrect, SDL_Surface * dst, const SDL_Rect * dstrect) { int src_locked; int dst_locked; int pos, inc; int dst_maxrow; int src_row, dst_row; Uint8 *srcp = NULL; Uint8 *dstp; SDL_Rect full_src; SDL_Rect full_dst; #ifdef USE_ASM_STRETCH SDL_bool use_asm = SDL_TRUE; #ifdef __GNUC__ int u1, u2; #endif #endif /* USE_ASM_STRETCH */ const int bpp = dst->format->BytesPerPixel; if (src->format->format != dst->format->format) { return SDL_SetError("Only works with same format surfaces"); } /* Verify the blit rectangles */ if (srcrect) { if ((srcrect->x < 0) || (srcrect->y < 0) || ((srcrect->x + srcrect->w) > src->w) || ((srcrect->y + srcrect->h) > src->h)) { return SDL_SetError("Invalid source blit rectangle"); } } else { full_src.x = 0; full_src.y = 0; full_src.w = src->w; full_src.h = src->h; srcrect = &full_src; } if (dstrect) { if ((dstrect->x < 0) || (dstrect->y < 0) || ((dstrect->x + dstrect->w) > dst->w) || ((dstrect->y + dstrect->h) > dst->h)) { return SDL_SetError("Invalid destination blit rectangle"); } } else { full_dst.x = 0; full_dst.y = 0; full_dst.w = dst->w; full_dst.h = dst->h; dstrect = &full_dst; } /* Lock the destination if it's in hardware */ dst_locked = 0; if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { return SDL_SetError("Unable to lock destination surface"); } dst_locked = 1; } /* Lock the source if it's in hardware */ src_locked = 0; if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { if (dst_locked) { SDL_UnlockSurface(dst); } return SDL_SetError("Unable to lock source surface"); } src_locked = 1; } /* Set up the data... */ pos = 0x10000; inc = (srcrect->h << 16) / dstrect->h; src_row = srcrect->y; dst_row = dstrect->y; #ifdef USE_ASM_STRETCH /* Write the opcodes for this stretch */ if ((bpp == 3) || (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0)) { use_asm = SDL_FALSE; } #endif /* Perform the stretch blit */ for (dst_maxrow = dst_row + dstrect->h; dst_row < dst_maxrow; ++dst_row) { dstp = (Uint8 *) dst->pixels + (dst_row * dst->pitch) + (dstrect->x * bpp); while (pos >= 0x10000L) { srcp = (Uint8 *) src->pixels + (src_row * src->pitch) + (srcrect->x * bpp); ++src_row; pos -= 0x10000L; } #ifdef USE_ASM_STRETCH if (use_asm) { #ifdef __GNUC__ __asm__ __volatile__("call *%4":"=&D"(u1), "=&S"(u2) :"0"(dstp), "1"(srcp), "r"(copy_row) :"memory"); #elif defined(_MSC_VER) || defined(__WATCOMC__) /* *INDENT-OFF* */ { void *code = copy_row; __asm { push edi push esi mov edi, dstp mov esi, srcp call dword ptr code pop esi pop edi } } /* *INDENT-ON* */ #else #error Need inline assembly for this compiler #endif } else #endif switch (bpp) { case 1: copy_row1(srcp, srcrect->w, dstp, dstrect->w); break; case 2: copy_row2((Uint16 *) srcp, srcrect->w, (Uint16 *) dstp, dstrect->w); break; case 3: copy_row3(srcp, srcrect->w, dstp, dstrect->w); break; case 4: copy_row4((Uint32 *) srcp, srcrect->w, (Uint32 *) dstp, dstrect->w); break; } pos += inc; }
/** * Perform a stretch blit between two image structs of the same format. * * @param src Source image. * @param srcrect Source rectangle. * @param dst Destination image. * @param dstrect Destination rectangle. */ void GdStretchImage(PMWIMAGEHDR src, MWCLIPRECT *srcrect, PMWIMAGEHDR dst, MWCLIPRECT *dstrect) { int pos, inc; int bytesperpixel; int dst_maxrow; int src_row, dst_row; MWUCHAR *srcp = 0; MWUCHAR *dstp; MWCLIPRECT full_src; MWCLIPRECT full_dst; if ( src->bytesperpixel != dst->bytesperpixel ) { EPRINTF("GdStretchImage: bytesperpixel mismatch\n"); return; } /* Verify the blit rectangles */ if ( srcrect ) { if ( (srcrect->x < 0) || (srcrect->y < 0) || ((srcrect->x+srcrect->width) > src->width) || ((srcrect->y+srcrect->height) > src->height) ) { EPRINTF("GdStretchImage: invalid source rect\n"); return; } } else { full_src.x = 0; full_src.y = 0; full_src.width = src->width; full_src.height = src->height; srcrect = &full_src; } if ( dstrect ) { /* if stretching to nothing, return*/ if (!dstrect->width || !dstrect->height) return; if ( (dstrect->x < 0) || (dstrect->y < 0) || ((dstrect->x+dstrect->width) > dst->width) || ((dstrect->y+dstrect->height) > dst->height) ) { EPRINTF("GdStretchImage: invalid dest rect\n"); return; } } else { full_dst.x = 0; full_dst.y = 0; full_dst.width = dst->width; full_dst.height = dst->height; dstrect = &full_dst; } /* Set up the data... */ pos = 0x10000; inc = (srcrect->height << 16) / dstrect->height; src_row = srcrect->y; dst_row = dstrect->y; bytesperpixel = dst->bytesperpixel; /* Perform the stretch blit */ for ( dst_maxrow = dst_row+dstrect->height; dst_row<dst_maxrow; ++dst_row ) { dstp = (MWUCHAR *)dst->imagebits + (dst_row*dst->pitch) + (dstrect->x*bytesperpixel); while ( pos >= 0x10000L ) { srcp = (MWUCHAR *)src->imagebits + (src_row*src->pitch) + (srcrect->x*bytesperpixel); ++src_row; pos -= 0x10000L; } switch (bytesperpixel) { case 1: copy_row1(srcp, srcrect->width, dstp, dstrect->width); break; case 2: copy_row2((unsigned short *)srcp, srcrect->width, (unsigned short *)dstp, dstrect->width); break; case 3: copy_row3(srcp, srcrect->width, dstp, dstrect->width); break; case 4: copy_row4((uint32_t *)srcp, srcrect->width, (uint32_t *)dstp, dstrect->width); break; } pos += inc; } }