From: YuriK7 riyu12383@gmail.com
--- dlls/wined3d/surface.c | 187 ++++++++++++++++++++++++++++++----------- 1 file changed, 139 insertions(+), 48 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 14cfebd7074..d5d5db37053 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -616,6 +616,7 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int const BYTE *sbase; const BYTE *sbuf; BYTE *dbuf; + BYTE* tmp_buffer;
TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_box %s, src_texture %p, " "src_sub_resource_idx %u, src_box %s, flags %#x, fx %p, filter %s.\n", @@ -808,11 +809,34 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int else { /* Stretching in y direction only. */ - for (y = sy = 0; y < dst_height; ++y, sy += yinc) + + /* Use a temporary buffer if blitting surface to itself */ + if (same_sub_resource) + tmp_buffer = malloc(dst_height*row_byte_count); + + if (same_sub_resource && tmp_buffer != NULL) { - sbuf = sbase + (sy >> 16) * src_map.row_pitch; - memcpy(dbuf, sbuf, row_byte_count); - dbuf += dst_map.row_pitch; + for (y = sy = 0; y < dst_height; ++y, sy += yinc) + { + sbuf = sbase + (sy >> 16) * src_map.row_pitch; + memcpy(tmp_buffer + y * row_byte_count, sbuf, row_byte_count); + } + for (y = 0; y < dst_height; ++y) + { + memcpy(dbuf, tmp_buffer + y * row_byte_count, row_byte_count); + dbuf += dst_map.row_pitch; + } + free(tmp_buffer); + } + else + { + /* Stretching without temporary buffer */ + for (y = sy = 0; y < dst_height; ++y, sy += yinc) + { + sbuf = sbase + (sy >> 16) * src_map.row_pitch; + memcpy(dbuf, sbuf, row_byte_count); + dbuf += dst_map.row_pitch; + } } } } @@ -820,64 +844,131 @@ static HRESULT surface_cpu_blt(struct wined3d_texture *dst_texture, unsigned int { /* Stretching in X direction. */ unsigned int last_sy = ~0u; - for (y = sy = 0; y < dst_height; ++y, sy += yinc) - { - sbuf = sbase + (sy >> 16) * src_map.row_pitch; - - if ((sy >> 16) == (last_sy >> 16)) - { - /* This source row is the same as last source row - - * Copy the already stretched row. */ - memcpy(dbuf, dbuf - dst_map.row_pitch, row_byte_count); - } - else - { -#define STRETCH_ROW(type) \ +#define STRETCH_ROW(type, dst_buf) \ do { \ const type *s = (const type *)sbuf; \ - type *d = (type *)dbuf; \ + type *d = (type *)dst_buf; \ for (x = sx = 0; x < dst_width; ++x, sx += xinc) \ d[x] = s[sx >> 16]; \ } while(0)
- switch(bpp) + /* Use a temporary buffer if blitting surface to itself */ + if (same_sub_resource) + tmp_buffer = malloc(dst_height*row_byte_count); + + if (same_sub_resource && tmp_buffer != NULL) + { + BYTE *buffer_ptr = tmp_buffer; + for (y = sy = 0; y < dst_height; ++y, sy += yinc) + { + sbuf = sbase + (sy >> 16) * src_map.row_pitch; + + if ((sy >> 16) == (last_sy >> 16)) { - case 1: - STRETCH_ROW(BYTE); - break; - case 2: - STRETCH_ROW(WORD); - break; - case 4: - STRETCH_ROW(DWORD); - break; - case 3: + /* This source row is the same as last source row - + * Copy the already stretched row. */ + memcpy(buffer_ptr, buffer_ptr - row_byte_count, row_byte_count); + } + else + { + switch(bpp) { - const BYTE *s; - BYTE *d = dbuf; - for (x = sx = 0; x < dst_width; x++, sx+= xinc) + case 1: + STRETCH_ROW(BYTE, buffer_ptr); + break; + case 2: + STRETCH_ROW(WORD, buffer_ptr); + break; + case 4: + STRETCH_ROW(DWORD, buffer_ptr); + break; + case 3: { - DWORD pixel; - - s = sbuf + 3 * (sx >> 16); - pixel = s[0] | (s[1] << 8) | (s[2] << 16); - d[0] = (pixel ) & 0xff; - d[1] = (pixel >> 8) & 0xff; - d[2] = (pixel >> 16) & 0xff; - d += 3; + const BYTE *s; + BYTE *d = buffer_ptr; + for (x = sx = 0; x < dst_width; x++, sx+= xinc) + { + DWORD pixel; + + s = sbuf + 3 * (sx >> 16); + pixel = s[0] | (s[1] << 8) | (s[2] << 16); + d[0] = (pixel ) & 0xff; + d[1] = (pixel >> 8) & 0xff; + d[2] = (pixel >> 16) & 0xff; + d += 3; + } + break; } - break; + default: + FIXME("Stretched blit not implemented for bpp %u.\n", bpp * 8); + hr = WINED3DERR_NOTAVAILABLE; + goto error; } - default: - FIXME("Stretched blit not implemented for bpp %u.\n", bpp * 8); - hr = WINED3DERR_NOTAVAILABLE; - goto error; } -#undef STRETCH_ROW + buffer_ptr += row_byte_count; + last_sy = sy; + } + for (y = 0; y < dst_height; ++y) + { + memcpy(dbuf, tmp_buffer + y * row_byte_count, row_byte_count); + dbuf += dst_map.row_pitch; } - dbuf += dst_map.row_pitch; - last_sy = sy; + free(tmp_buffer); } + else + { + /* Stretching without temporary buffer */ + for (y = sy = 0; y < dst_height; ++y, sy += yinc) + { + sbuf = sbase + (sy >> 16) * src_map.row_pitch; + + if ((sy >> 16) == (last_sy >> 16)) + { + /* This source row is the same as last source row - + * Copy the already stretched row. */ + memcpy(dbuf, dbuf - dst_map.row_pitch, row_byte_count); + } + else + { + switch(bpp) + { + case 1: + STRETCH_ROW(BYTE, dbuf); + break; + case 2: + STRETCH_ROW(WORD, dbuf); + break; + case 4: + STRETCH_ROW(DWORD, dbuf); + break; + case 3: + { + const BYTE *s; + BYTE *d = dbuf; + for (x = sx = 0; x < dst_width; x++, sx+= xinc) + { + DWORD pixel; + + s = sbuf + 3 * (sx >> 16); + pixel = s[0] | (s[1] << 8) | (s[2] << 16); + d[0] = (pixel ) & 0xff; + d[1] = (pixel >> 8) & 0xff; + d[2] = (pixel >> 16) & 0xff; + d += 3; + } + break; + } + default: + FIXME("Stretched blit not implemented for bpp %u.\n", bpp * 8); + hr = WINED3DERR_NOTAVAILABLE; + goto error; + } + } + dbuf += dst_map.row_pitch; + last_sy = sy; + } + } +#undef STRETCH_ROW } } else