From 0997f514c47fe7df17d4ecfa358d9682dd07a65a Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Thu, 8 Sep 2022 02:19:15 +0200 Subject: [PATCH] separate blitters into a different file --- cnc-ddraw.vcxproj | 2 + cnc-ddraw.vcxproj.filters | 6 + inc/blt.h | 93 +++++ src/blt.c | 660 ++++++++++++++++++++++++++++++++ src/ddsurface.c | 769 ++++++++------------------------------ src/render_d3d9.c | 24 +- 6 files changed, 935 insertions(+), 619 deletions(-) create mode 100644 inc/blt.h create mode 100644 src/blt.c diff --git a/cnc-ddraw.vcxproj b/cnc-ddraw.vcxproj index 39f0eb1..4cde61e 100644 --- a/cnc-ddraw.vcxproj +++ b/cnc-ddraw.vcxproj @@ -15,6 +15,7 @@ + @@ -61,6 +62,7 @@ + diff --git a/cnc-ddraw.vcxproj.filters b/cnc-ddraw.vcxproj.filters index 6e0e134..6871a26 100644 --- a/cnc-ddraw.vcxproj.filters +++ b/cnc-ddraw.vcxproj.filters @@ -153,6 +153,9 @@ Source Files + + Source Files + @@ -263,6 +266,9 @@ Header Files + + Header Files + diff --git a/inc/blt.h b/inc/blt.h new file mode 100644 index 0000000..f216988 --- /dev/null +++ b/inc/blt.h @@ -0,0 +1,93 @@ +#ifndef BLT_H +#define BLT_H + +#define WIN32_LEAN_AND_MEAN +#include + + +void blt_clean( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_p, + int bpp); + +void blt_overlap( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_p, + int bpp); + +void blt_colorkey( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_p, + unsigned int key_low, + unsigned int key_high, + int bpp); + +void blt_colorkey_mirror_stretch( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_w, + int src_h, + int src_p, + unsigned int key_low, + unsigned int key_high, + BOOL mirror_up_down, + BOOL mirror_left_right, + int bpp); + +void blt_colorfill( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned int color, + int bpp); + +void blt_stretch( + unsigned char* dst_buf, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src_buf, + int src_x, + int src_y, + int src_w, + int src_h, + int src_p, + int bpp); + +#endif diff --git a/src/blt.c b/src/blt.c new file mode 100644 index 0000000..79d9314 --- /dev/null +++ b/src/blt.c @@ -0,0 +1,660 @@ +#include +#include "debug.h" +#include "scale_pattern.h" +#include "blt.h" + + +void blt_clean( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_p, + int bpp) +{ + int bytes_pp = bpp / 8; + + size_t size = dst_w * bytes_pp; + + src += (src_x * bytes_pp) + (src_p * src_y); + dst += (dst_x * bytes_pp) + (dst_p * dst_y); + + for (int i = 0; i < dst_h; i++) + { + memcpy(dst, src, size); + + src += src_p; + dst += dst_p; + } +} + +void blt_overlap( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_p, + int bpp) +{ + int bytes_pp = bpp / 8; + + size_t size = dst_w * bytes_pp; + + src += (src_x * bytes_pp) + (src_p * src_y); + dst += (dst_x * bytes_pp) + (dst_p * dst_y); + + if (dst_y > src_y) + { + src += src_p * dst_h; + dst += dst_p * dst_h; + + for (int i = dst_h; i-- > 0;) + { + src -= src_p; + dst -= dst_p; + + memmove(dst, src, size); + } + } + else + { + for (int i = 0; i < dst_h; i++) + { + memmove(dst, src, size); + + src += src_p; + dst += dst_p; + } + } +} + +void blt_colorkey( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_p, + unsigned int key_low, + unsigned int key_high, + int bpp) +{ + int bytes_pp = bpp / 8; + + size_t d_p = dst_p - (dst_w * bytes_pp); + size_t s_p = src_p - (dst_w * bytes_pp); + + src += (src_x * bytes_pp) + (src_p * src_y); + dst += (dst_x * bytes_pp) + (dst_p * dst_y); + + if (bpp == 8) + { + unsigned char key_l = (unsigned char)key_low; + unsigned char key_h = (unsigned char)key_high; + + if (key_l == key_h) + { + for (int y = 0; y < dst_h; y++) + { + for (int x = 0; x < dst_w; x++) + { + unsigned char c = *src++; + + if (c != key_l) + { + *dst = c; + } + + dst++; + } + + src += s_p; + dst += d_p; + } + } + else + { + for (int y = 0; y < dst_h; y++) + { + for (int x = 0; x < dst_w; x++) + { + unsigned char c = *src++; + + if (c < key_l || c > key_h) + { + *dst = c; + } + + dst++; + } + + src += s_p; + dst += d_p; + } + } + } + else if (bpp == 16) + { + unsigned short key_l = (unsigned short)key_low; + unsigned short key_h = (unsigned short)key_high; + + if (key_l == key_h) + { + for (int y = 0; y < dst_h; y++) + { + for (int x = 0; x < dst_w; x++) + { + unsigned short c = *((unsigned short*)src)++; + + if (c != key_l) + { + *((unsigned short*)dst) = c; + } + + ((unsigned short*)dst)++; + } + + src += s_p; + dst += d_p; + } + } + else + { + for (int y = 0; y < dst_h; y++) + { + for (int x = 0; x < dst_w; x++) + { + unsigned short c = *((unsigned short*)src)++; + + if (c < key_l || c > key_h) + { + *((unsigned short*)dst) = c; + } + + ((unsigned short*)dst)++; + } + + src += s_p; + dst += d_p; + } + } + } + else if (bpp == 32) + { + unsigned int key_l = (unsigned int)key_low; + unsigned int key_h = (unsigned int)key_high; + + if (key_l == key_h) + { + for (int y = 0; y < dst_h; y++) + { + for (int x = 0; x < dst_w; x++) + { + unsigned int c = *((unsigned int*)src)++; + + if (c != key_l) + { + *((unsigned int*)dst) = c; + } + + ((unsigned int*)dst)++; + } + + src += s_p; + dst += d_p; + } + } + else + { + for (int y = 0; y < dst_h; y++) + { + for (int x = 0; x < dst_w; x++) + { + unsigned int c = *((unsigned int*)src)++; + + if (c < key_l || c > key_h) + { + *((unsigned int*)dst) = c; + } + + ((unsigned int*)dst)++; + } + + src += s_p; + dst += d_p; + } + } + } +} + +void blt_colorkey_mirror_stretch( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src, + int src_x, + int src_y, + int src_w, + int src_h, + int src_p, + unsigned int key_low, + unsigned int key_high, + BOOL mirror_up_down, + BOOL mirror_left_right, + int bpp) +{ + int bytes_pp = bpp / 8; + + int dst_surf_w = dst_p / bytes_pp; + int src_surf_w = src_p / bytes_pp; + + float scale_w = (float)src_w / dst_w; + float scale_h = (float)src_h / dst_h; + + if (bpp == 8) + { + unsigned char key_l = (unsigned char)key_low; + unsigned char key_h = (unsigned char)key_high; + + for (int y = 0; y < dst_h; y++) + { + int scaled_y = (int)(y * scale_h); + + if (mirror_up_down) + scaled_y = src_h - 1 - scaled_y; + + int src_row = src_surf_w * (scaled_y + src_y); + int dst_row = dst_surf_w * (y + dst_y); + + for (int x = 0; x < dst_w; x++) + { + int scaled_x = (int)(x * scale_w); + + if (mirror_left_right) + scaled_x = src_w - 1 - scaled_x; + + unsigned char c = ((unsigned char*)src)[scaled_x + src_x + src_row]; + + if (c < key_l || c > key_h) + { + ((unsigned char*)dst)[x + dst_x + dst_row] = c; + } + } + } + } + else if (bpp == 16) + { + unsigned short key_l = (unsigned short)key_low; + unsigned short key_h = (unsigned short)key_high; + + for (int y = 0; y < dst_h; y++) + { + int scaled_y = (int)(y * scale_h); + + if (mirror_up_down) + scaled_y = src_h - 1 - scaled_y; + + int src_row = src_surf_w * (scaled_y + src_y); + int dst_row = dst_surf_w * (y + dst_y); + + for (int x = 0; x < dst_w; x++) + { + int scaled_x = (int)(x * scale_w); + + if (mirror_left_right) + scaled_x = src_w - 1 - scaled_x; + + unsigned short c = ((unsigned short*)src)[scaled_x + src_x + src_row]; + + if (c < key_l || c > key_h) + { + ((unsigned short*)dst)[x + dst_x + dst_row] = c; + } + } + } + } + else if (bpp == 32) + { + unsigned int key_l = (unsigned int)key_low; + unsigned int key_h = (unsigned int)key_high; + + for (int y = 0; y < dst_h; y++) + { + int scaled_y = (int)(y * scale_h); + + if (mirror_up_down) + scaled_y = src_h - 1 - scaled_y; + + int src_row = src_surf_w * (scaled_y + src_y); + int dst_row = dst_surf_w * (y + dst_y); + + for (int x = 0; x < dst_w; x++) + { + int scaled_x = (int)(x * scale_w); + + if (mirror_left_right) + scaled_x = src_w - 1 - scaled_x; + + unsigned int c = ((unsigned int*)src)[scaled_x + src_x + src_row]; + + if (c < key_l || c > key_h) + { + ((unsigned int*)dst)[x + dst_x + dst_row] = c; + } + } + } + } +} + +void blt_colorfill( + unsigned char* dst, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned int color, + int bpp) +{ + int bytes_pp = bpp / 8; + + size_t size = dst_w * bytes_pp; + + dst += (dst_x * bytes_pp) + (dst_p * dst_y); + + if (bpp == 8) + { + for (int i = 0; i < dst_h; i++) + { + memset(dst, color, size); + dst += dst_p; + } + } + else if (bpp == 16) + { + if ((color & 0xFF) == ((color >> 8) & 0xFF)) + { + for (int i = 0; i < dst_h; i++) + { + memset(dst, color, size); + dst += dst_p; + } + } + else + { + unsigned short* first_row = (unsigned short*)dst; + + for (int x = 0; x < dst_w; x++) + { + first_row[x] = (unsigned short)color; + } + + for (int i = 1; i < dst_h; i++) + { + dst += dst_p; + memcpy(dst, first_row, size); + } + } + } + else if (bpp == 32) + { + if ((color & 0xFF) == ((color >> 8) & 0xFF) && + (color & 0xFF) == ((color >> 16) & 0xFF) && + (color & 0xFF) == ((color >> 24) & 0xFF)) + { + for (int i = 0; i < dst_h; i++) + { + memset(dst, color, size); + dst += dst_p; + } + } + else + { + unsigned int* first_row = (unsigned int*)dst; + + for (int x = 0; x < dst_w; x++) + { + first_row[x] = color; + } + + for (int i = 1; i < dst_h; i++) + { + dst += dst_p; + memcpy(dst, first_row, size); + } + } + } +} + +void blt_stretch( + unsigned char* dst_buf, + int dst_x, + int dst_y, + int dst_w, + int dst_h, + int dst_p, + unsigned char* src_buf, + int src_x, + int src_y, + int src_w, + int src_h, + int src_p, + int bpp) +{ + /* Linear scaling using integer math + * Since the scaling pattern for x will aways be the same, the pattern itself gets pre-calculated + * and stored in an array. + * Y scaling pattern gets calculated during the blit loop + */ + unsigned int x_ratio = (unsigned int)((src_w << 16) / dst_w) + 1; + unsigned int y_ratio = (unsigned int)((src_h << 16) / dst_h) + 1; + + unsigned int s_src_x, s_src_y; + unsigned int dest_base, source_base; + + scale_pattern* pattern = malloc((dst_w + 1) * (sizeof(scale_pattern))); + int pattern_idx = 0; + unsigned int last_src_x = 0; + + if (pattern != NULL) + { + pattern[pattern_idx] = (scale_pattern){ ONCE, 0, 0, 1 }; + + /* Build the pattern! */ + int x; + for (x = 1; x < dst_w; x++) { + s_src_x = (x * x_ratio) >> 16; + if (s_src_x == last_src_x) + { + if (pattern[pattern_idx].type == REPEAT || pattern[pattern_idx].type == ONCE) + { + pattern[pattern_idx].type = REPEAT; + pattern[pattern_idx].count++; + } + else if (pattern[pattern_idx].type == SEQUENCE) + { + pattern_idx++; + pattern[pattern_idx] = (scale_pattern){ REPEAT, x, s_src_x, 1 }; + } + } + else if (s_src_x == last_src_x + 1) + { + if (pattern[pattern_idx].type == SEQUENCE || pattern[pattern_idx].type == ONCE) + { + pattern[pattern_idx].type = SEQUENCE; + pattern[pattern_idx].count++; + } + else if (pattern[pattern_idx].type == REPEAT) + { + pattern_idx++; + pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 }; + } + } + else + { + pattern_idx++; + pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 }; + } + last_src_x = s_src_x; + } + pattern[pattern_idx + 1] = (scale_pattern){ END, 0, 0, 0 }; + + + /* Do the actual blitting */ + int bytes_pp = bpp / 8; + int dst_surf_w = dst_p / bytes_pp; + int src_surf_w = src_p / bytes_pp; + + int count = 0; + int y; + + for (y = 0; y < dst_h; y++) { + + dest_base = dst_x + dst_surf_w * (y + dst_y); + + s_src_y = (y * y_ratio) >> 16; + + source_base = src_x + src_surf_w * (s_src_y + src_y); + + pattern_idx = 0; + scale_pattern* current = &pattern[pattern_idx]; + + if (bpp == 8) + { + unsigned char* d, * s, v; + unsigned char* src = (unsigned char*)src_buf; + unsigned char* dst = (unsigned char*)dst_buf; + + do { + switch (current->type) + { + case ONCE: + dst[dest_base + current->dst_index] = + src[source_base + current->src_index]; + break; + + case REPEAT: + d = (dst + dest_base + current->dst_index); + v = src[source_base + current->src_index]; + + count = current->count; + while (count-- > 0) + *d++ = v; + + break; + + case SEQUENCE: + d = dst + dest_base + current->dst_index; + s = src + source_base + current->src_index; + + memcpy((void*)d, (void*)s, current->count); + break; + + case END: + default: + break; + } + + current = &pattern[++pattern_idx]; + } while (current->type != END); + } + else if (bpp == 16) + { + unsigned short* d, * s, v; + unsigned short* src = (unsigned short*)src_buf; + unsigned short* dst = (unsigned short*)dst_buf; + + do { + switch (current->type) + { + case ONCE: + dst[dest_base + current->dst_index] = + src[source_base + current->src_index]; + break; + + case REPEAT: + d = (dst + dest_base + current->dst_index); + v = src[source_base + current->src_index]; + + count = current->count; + while (count-- > 0) + *d++ = v; + + break; + + case SEQUENCE: + d = dst + dest_base + current->dst_index; + s = src + source_base + current->src_index; + + memcpy((void*)d, (void*)s, current->count * bytes_pp); + break; + + case END: + default: + break; + } + + current = &pattern[++pattern_idx]; + } while (current->type != END); + } + else if (bpp == 32) + { + unsigned int* d, * s, v; + unsigned int* src = (unsigned int*)src_buf; + unsigned int* dst = (unsigned int*)dst_buf; + + do { + switch (current->type) + { + case ONCE: + dst[dest_base + current->dst_index] = + src[source_base + current->src_index]; + break; + + case REPEAT: + d = (dst + dest_base + current->dst_index); + v = src[source_base + current->src_index]; + + count = current->count; + while (count-- > 0) + *d++ = v; + + break; + + case SEQUENCE: + d = dst + dest_base + current->dst_index; + s = src + source_base + current->src_index; + + memcpy((void*)d, (void*)s, current->count * bytes_pp); + break; + + case END: + default: + break; + } + + current = &pattern[++pattern_idx]; + } while (current->type != END); + } + } + free(pattern); + } + +} diff --git a/src/ddsurface.c b/src/ddsurface.c index dd84191..9eb784b 100644 --- a/src/ddsurface.c +++ b/src/ddsurface.c @@ -5,11 +5,11 @@ #include "hook.h" #include "ddsurface.h" #include "mouse.h" -#include "scale_pattern.h" #include "IDirectDrawSurface.h" #include "winapi_hooks.h" #include "debug.h" #include "utils.h" +#include "blt.h" HRESULT dds_AddAttachedSurface(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceImpl* lpDDSurface) @@ -29,11 +29,11 @@ HRESULT dds_AddAttachedSurface(IDirectDrawSurfaceImpl* This, IDirectDrawSurfaceI } HRESULT dds_Blt( - IDirectDrawSurfaceImpl* This, - LPRECT lpDestRect, - IDirectDrawSurfaceImpl* lpDDSrcSurface, - LPRECT lpSrcRect, - DWORD dwFlags, + IDirectDrawSurfaceImpl* This, + LPRECT lpDestRect, + IDirectDrawSurfaceImpl* lpDDSrcSurface, + LPRECT lpSrcRect, + DWORD dwFlags, LPDDBLTFX lpDDBltFx) { dbg_dump_dds_blt_flags(dwFlags); @@ -121,79 +121,17 @@ HRESULT dds_Blt( void* dst_buf = dds_GetBuffer(This); void* src_buf = dds_GetBuffer(src_surface); - if (dst_buf && (dwFlags & DDBLT_COLORFILL) && dst_w > 0 && dst_h > 0) + if (dst_buf && (dwFlags & DDBLT_COLORFILL) && lpDDBltFx && dst_w > 0 && dst_h > 0) { - unsigned char* dst = (unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y); - unsigned char* first_row = dst; - unsigned int dst_pitch = dst_w * This->lx_pitch; - int x, i; - - if (This->bpp == 8) - { - unsigned char color = (unsigned char)lpDDBltFx->dwFillColor; - - for (i = 0; i < dst_h; i++) - { - memset(dst, color, dst_pitch); - dst += This->l_pitch; - } - } - else if (This->bpp == 16) - { - unsigned short* row1 = (unsigned short*)dst; - unsigned short color = (unsigned short)lpDDBltFx->dwFillColor; - - if ((color & 0xFF) == (color >> 8)) - { - unsigned char c8 = (unsigned char)(color & 0xFF); - - for (i = 0; i < dst_h; i++) - { - memset(dst, c8, dst_pitch); - dst += This->l_pitch; - } - } - else - { - for (x = 0; x < dst_w; x++) - row1[x] = color; - - for (i = 1; i < dst_h; i++) - { - dst += This->l_pitch; - memcpy(dst, first_row, dst_pitch); - } - } - } - else if (This->bpp == 32) - { - unsigned int* row1 = (unsigned int*)dst; - unsigned int color = lpDDBltFx->dwFillColor; - - if ((color & 0xFF) == ((color >> 8) & 0xFF) && - (color & 0xFF) == ((color >> 16) & 0xFF) && - (color & 0xFF) == ((color >> 24) & 0xFF)) - { - unsigned char c8 = (unsigned char)(color & 0xFF); - - for (i = 0; i < dst_h; i++) - { - memset(dst, c8, dst_pitch); - dst += This->l_pitch; - } - } - else - { - for (x = 0; x < dst_w; x++) - row1[x] = color; - - for (i = 1; i < dst_h; i++) - { - dst += This->l_pitch; - memcpy(dst, first_row, dst_pitch); - } - } - } + blt_colorfill( + dst_buf, + dst_x, + dst_y, + dst_w, + dst_h, + This->l_pitch, + lpDDBltFx->dwFillColor, + This->bpp); } if (src_surface && src_w > 0 && src_h > 0 && dst_w > 0 && dst_h > 0) @@ -215,8 +153,8 @@ HRESULT dds_Blt( StretchBlt(dst_dc, dst_x, dst_y, dst_w, dst_h, src_dc, src_x, src_y, src_w, src_h, SRCCOPY); } else if ( - (dwFlags & DDBLT_KEYSRC) || - (dwFlags & DDBLT_KEYSRCOVERRIDE) || + (dwFlags & DDBLT_KEYSRC) || + (dwFlags & DDBLT_KEYSRCOVERRIDE) || mirror_left_right || mirror_up_down) { @@ -236,410 +174,91 @@ HRESULT dds_Blt( color_key.dwColorSpaceHighValue = color_key.dwColorSpaceLowValue; } - float scale_w = (float)src_w / dst_w; - float scale_h = (float)src_h / dst_h; - - if (This->bpp == 8) + if (src_w == dst_w && src_h == dst_h && !mirror_left_right && !mirror_up_down) { - unsigned char key_low = (unsigned char)color_key.dwColorSpaceLowValue; - unsigned char key_high = (unsigned char)color_key.dwColorSpaceHighValue; - - /* - if (src_w == dst_w && src_h == dst_h && !mirror_left_right && !mirror_up_down) - { - unsigned char* src = - (unsigned char*)src_buf + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y); - - unsigned char* dst = - (unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y); - - unsigned int dst_p = This->l_pitch - (dst_w * This->lx_pitch); - unsigned int src_p = src_surface->l_pitch - (dst_w * src_surface->lx_pitch); - - if (key_low == key_high) - { - for (int y = 0; y < dst_h; y++) - { - for (int x = 0; x < dst_w; x++) - { - unsigned char c = *src++; - - if (c != key_low) - { - *dst = c; - } - - dst++; - } - - src += src_p; - dst += dst_p; - } - } - else - { - for (int i = 0; i < dst_h; i++) - { - for (int x = 0; x < dst_w; x++) - { - unsigned char c = *src++; - - if (c < key_low || c > key_high) - { - *dst = c; - } - - dst++; - } - - src += src_p; - dst += dst_p; - } - } - } - else - { - */ - for (int y = 0; y < dst_h; y++) - { - int scaled_y = (int)(y * scale_h); - - if (mirror_up_down) - scaled_y = src_h - 1 - scaled_y; - - int src_row = src_surface->width * (scaled_y + src_y); - int dst_row = This->width * (y + dst_y); - - for (int x = 0; x < dst_w; x++) - { - int scaled_x = (int)(x * scale_w); - - if (mirror_left_right) - scaled_x = src_w - 1 - scaled_x; - - unsigned char c = ((unsigned char*)src_buf)[scaled_x + src_x + src_row]; - - if (c < key_low || c > key_high) - { - ((unsigned char*)dst_buf)[x + dst_x + dst_row] = c; - } - } - } - //} - } - else if (This->bpp == 16) - { - unsigned short key_low = (unsigned short)color_key.dwColorSpaceLowValue; - unsigned short key_high = (unsigned short)color_key.dwColorSpaceHighValue; - - for (int y = 0; y < dst_h; y++) - { - int scaled_y = (int)(y * scale_h); - - if (mirror_up_down) - scaled_y = src_h - 1 - scaled_y; - - int src_row = src_surface->width * (scaled_y + src_y); - int dst_row = This->width * (y + dst_y); - - for (int x = 0; x < dst_w; x++) - { - int scaled_x = (int)(x * scale_w); - - if (mirror_left_right) - scaled_x = src_w - 1 - scaled_x; - - unsigned short c = ((unsigned short*)src_buf)[scaled_x + src_x + src_row]; - - if (c < key_low || c > key_high) - { - ((unsigned short*)dst_buf)[x + dst_x + dst_row] = c; - } - } - } - } - else if (This->bpp == 32) - { - unsigned int key_low = color_key.dwColorSpaceLowValue; - unsigned int key_high = color_key.dwColorSpaceHighValue; - - for (int y = 0; y < dst_h; y++) - { - int scaled_y = (int)(y * scale_h); - - if (mirror_up_down) - scaled_y = src_h - 1 - scaled_y; - - int src_row = src_surface->width * (scaled_y + src_y); - int dst_row = This->width * (y + dst_y); - - for (int x = 0; x < dst_w; x++) - { - int scaled_x = (int)(x * scale_w); - - if (mirror_left_right) - scaled_x = src_w - 1 - scaled_x; - - unsigned int c = ((unsigned int*)src_buf)[scaled_x + src_x + src_row]; - - if (c < key_low || c > key_high) - { - ((unsigned int*)dst_buf)[x + dst_x + dst_row] = c; - } - } - } - } - } - else - { - if (!is_stretch_blt) - { - int width = dst_w > src_w ? src_w : dst_w; - int height = dst_h > src_h ? src_h : dst_h; - - unsigned char* src = - (unsigned char*)src_buf + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y); - - unsigned char* dst = - (unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y); - - unsigned int dst_pitch = width * This->lx_pitch; - - if (This == src_surface) - { - if (dst_y > src_y) - { - src += src_surface->l_pitch * height; - dst += This->l_pitch * height; - - for (int i = height; i-- > 0;) - { - src -= src_surface->l_pitch; - dst -= This->l_pitch; - - memmove(dst, src, dst_pitch); - } - } - else - { - for (int i = 0; i < height; i++) - { - memmove(dst, src, dst_pitch); - - src += src_surface->l_pitch; - dst += This->l_pitch; - } - } - } - else - { - for (int i = 0; i < height; i++) - { - memcpy(dst, src, dst_pitch); - - src += src_surface->l_pitch; - dst += This->l_pitch; - } - } + blt_colorkey( + dst_buf, + dst_x, + dst_y, + dst_w, + dst_h, + This->l_pitch, + src_buf, + src_x, + src_y, + src_surface->l_pitch, + color_key.dwColorSpaceLowValue, + color_key.dwColorSpaceHighValue, + This->bpp); } else { - /* Linear scaling using integer math - * Since the scaling pattern for x will aways be the same, the pattern itself gets pre-calculated - * and stored in an array. - * Y scaling pattern gets calculated during the blit loop - */ - unsigned int x_ratio = (unsigned int)((src_w << 16) / dst_w) + 1; - unsigned int y_ratio = (unsigned int)((src_h << 16) / dst_h) + 1; - - unsigned int s_src_x, s_src_y; - unsigned int dest_base, source_base; - - scale_pattern* pattern = malloc((dst_w + 1) * (sizeof(scale_pattern))); - int pattern_idx = 0; - unsigned int last_src_x = 0; - - if (pattern != NULL) - { - pattern[pattern_idx] = (scale_pattern){ ONCE, 0, 0, 1 }; - - /* Build the pattern! */ - int x; - for (x = 1; x < dst_w; x++) { - s_src_x = (x * x_ratio) >> 16; - if (s_src_x == last_src_x) - { - if (pattern[pattern_idx].type == REPEAT || pattern[pattern_idx].type == ONCE) - { - pattern[pattern_idx].type = REPEAT; - pattern[pattern_idx].count++; - } - else if (pattern[pattern_idx].type == SEQUENCE) - { - pattern_idx++; - pattern[pattern_idx] = (scale_pattern){ REPEAT, x, s_src_x, 1 }; - } - } - else if (s_src_x == last_src_x + 1) - { - if (pattern[pattern_idx].type == SEQUENCE || pattern[pattern_idx].type == ONCE) - { - pattern[pattern_idx].type = SEQUENCE; - pattern[pattern_idx].count++; - } - else if (pattern[pattern_idx].type == REPEAT) - { - pattern_idx++; - pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 }; - } - } - else - { - pattern_idx++; - pattern[pattern_idx] = (scale_pattern){ ONCE, x, s_src_x, 1 }; - } - last_src_x = s_src_x; - } - pattern[pattern_idx + 1] = (scale_pattern){ END, 0, 0, 0 }; - - - /* Do the actual blitting */ - int count = 0; - int y; - - for (y = 0; y < dst_h; y++) { - - dest_base = dst_x + This->width * (y + dst_y); - - s_src_y = (y * y_ratio) >> 16; - - source_base = src_x + src_surface->width * (s_src_y + src_y); - - pattern_idx = 0; - scale_pattern* current = &pattern[pattern_idx]; - - if (This->bpp == 8) - { - unsigned char* d, * s, v; - unsigned char* src = (unsigned char*)src_buf; - unsigned char* dst = (unsigned char*)dst_buf; - - do { - switch (current->type) - { - case ONCE: - dst[dest_base + current->dst_index] = - src[source_base + current->src_index]; - break; - - case REPEAT: - d = (dst + dest_base + current->dst_index); - v = src[source_base + current->src_index]; - - count = current->count; - while (count-- > 0) - *d++ = v; - - break; - - case SEQUENCE: - d = dst + dest_base + current->dst_index; - s = src + source_base + current->src_index; - - memcpy((void*)d, (void*)s, current->count * This->lx_pitch); - break; - - case END: - default: - break; - } - - current = &pattern[++pattern_idx]; - } while (current->type != END); - } - else if (This->bpp == 16) - { - unsigned short* d, * s, v; - unsigned short* src = (unsigned short*)src_buf; - unsigned short* dst = (unsigned short*)dst_buf; - - do { - switch (current->type) - { - case ONCE: - dst[dest_base + current->dst_index] = - src[source_base + current->src_index]; - break; - - case REPEAT: - d = (dst + dest_base + current->dst_index); - v = src[source_base + current->src_index]; - - count = current->count; - while (count-- > 0) - *d++ = v; - - break; - - case SEQUENCE: - d = dst + dest_base + current->dst_index; - s = src + source_base + current->src_index; - - memcpy((void*)d, (void*)s, current->count * This->lx_pitch); - break; - - case END: - default: - break; - } - - current = &pattern[++pattern_idx]; - } while (current->type != END); - } - else if (This->bpp == 32) - { - unsigned int* d, * s, v; - unsigned int* src = (unsigned int*)src_buf; - unsigned int* dst = (unsigned int*)dst_buf; - - do { - switch (current->type) - { - case ONCE: - dst[dest_base + current->dst_index] = - src[source_base + current->src_index]; - break; - - case REPEAT: - d = (dst + dest_base + current->dst_index); - v = src[source_base + current->src_index]; - - count = current->count; - while (count-- > 0) - *d++ = v; - - break; - - case SEQUENCE: - d = dst + dest_base + current->dst_index; - s = src + source_base + current->src_index; - - memcpy((void*)d, (void*)s, current->count * This->lx_pitch); - break; - - case END: - default: - break; - } - - current = &pattern[++pattern_idx]; - } while (current->type != END); - } - } - free(pattern); - } + blt_colorkey_mirror_stretch( + dst_buf, + dst_x, + dst_y, + dst_w, + dst_h, + This->l_pitch, + src_buf, + src_x, + src_y, + src_w, + src_h, + src_surface->l_pitch, + color_key.dwColorSpaceLowValue, + color_key.dwColorSpaceHighValue, + mirror_up_down, + mirror_left_right, + This->bpp); } - + } + else if (is_stretch_blt) + { + blt_stretch( + dst_buf, + dst_x, + dst_y, + dst_w, + dst_h, + This->l_pitch, + src_buf, + src_x, + src_y, + src_w, + src_h, + src_surface->l_pitch, + This->bpp); + } + else if (This == src_surface) + { + blt_overlap( + dst_buf, + dst_x, + dst_y, + min(dst_w, src_w), + min(dst_h, src_h), + This->l_pitch, + src_buf, + src_x, + src_y, + src_surface->l_pitch, + This->bpp); + } + else + { + blt_clean( + dst_buf, + dst_x, + dst_y, + min(dst_w, src_w), + min(dst_h, src_h), + This->l_pitch, + src_buf, + src_x, + src_y, + src_surface->l_pitch, + This->bpp); } } @@ -666,11 +285,11 @@ HRESULT dds_Blt( } HRESULT dds_BltFast( - IDirectDrawSurfaceImpl* This, - DWORD dwX, - DWORD dwY, - IDirectDrawSurfaceImpl* lpDDSrcSurface, - LPRECT lpSrcRect, + IDirectDrawSurfaceImpl* This, + DWORD dwX, + DWORD dwY, + IDirectDrawSurfaceImpl* lpDDSrcSurface, + LPRECT lpSrcRect, DWORD dwFlags) { dbg_dump_dds_blt_fast_flags(dwFlags); @@ -772,116 +391,50 @@ HRESULT dds_BltFast( } else if (dwFlags & DDBLTFAST_SRCCOLORKEY) { - if (This->bpp == 8) - { - unsigned char key_low = (unsigned char)src_surface->color_key.dwColorSpaceLowValue; - unsigned char key_high = (unsigned char)src_surface->color_key.dwColorSpaceHighValue; - - for (int y = 0; y < dst_h; y++) - { - int dst_row = This->width * (y + dst_y); - int src_row = src_surface->width * (y + src_y); - - for (int x = 0; x < dst_w; x++) - { - unsigned char c = ((unsigned char*)src_buf)[x + src_x + src_row]; - - if (c < key_low || c > key_high) - { - ((unsigned char*)dst_buf)[x + dst_x + dst_row] = c; - } - } - } - } - else if (This->bpp == 16) - { - unsigned short key_low = (unsigned short)src_surface->color_key.dwColorSpaceLowValue; - unsigned short key_high = (unsigned short)src_surface->color_key.dwColorSpaceHighValue; - - for (int y = 0; y < dst_h; y++) - { - int dst_row = This->width * (y + dst_y); - int src_row = src_surface->width * (y + src_y); - - for (int x = 0; x < dst_w; x++) - { - unsigned short c = ((unsigned short*)src_buf)[x + src_x + src_row]; - - if (c < key_low || c > key_high) - { - ((unsigned short*)dst_buf)[x + dst_x + dst_row] = c; - } - } - } - } - else if (This->bpp == 32) - { - unsigned int key_low = src_surface->color_key.dwColorSpaceLowValue; - unsigned int key_high = src_surface->color_key.dwColorSpaceHighValue; - - for (int y = 0; y < dst_h; y++) - { - int dst_row = This->width * (y + dst_y); - int src_row = src_surface->width * (y + src_y); - - for (int x = 0; x < dst_w; x++) - { - unsigned int c = ((unsigned int*)src_buf)[x + src_x + src_row]; - - if (c < key_low || c > key_high) - { - ((unsigned int*)dst_buf)[x + dst_x + dst_row] = c; - } - } - } - } + blt_colorkey( + dst_buf, + dst_x, + dst_y, + dst_w, + dst_h, + This->l_pitch, + src_buf, + src_x, + src_y, + src_surface->l_pitch, + src_surface->color_key.dwColorSpaceLowValue, + src_surface->color_key.dwColorSpaceHighValue, + This->bpp); + } + else if (This == src_surface) + { + blt_overlap( + dst_buf, + dst_x, + dst_y, + dst_w, + dst_h, + This->l_pitch, + src_buf, + src_x, + src_y, + src_surface->l_pitch, + This->bpp); } else { - unsigned char* src = - (unsigned char*)src_buf + (src_x * src_surface->lx_pitch) + (src_surface->l_pitch * src_y); - - unsigned char* dst = - (unsigned char*)dst_buf + (dst_x * This->lx_pitch) + (This->l_pitch * dst_y); - - unsigned int dst_pitch = dst_w * This->lx_pitch; - - if (This == src_surface) - { - if (dst_y > src_y) - { - src += src_surface->l_pitch * dst_h; - dst += This->l_pitch * dst_h; - - for (int i = dst_h; i-- > 0;) - { - src -= src_surface->l_pitch; - dst -= This->l_pitch; - - memmove(dst, src, dst_pitch); - } - } - else - { - for (int i = 0; i < dst_h; i++) - { - memmove(dst, src, dst_pitch); - - src += src_surface->l_pitch; - dst += This->l_pitch; - } - } - } - else - { - for (int i = 0; i < dst_h; i++) - { - memcpy(dst, src, dst_pitch); - - src += src_surface->l_pitch; - dst += This->l_pitch; - } - } + blt_clean( + dst_buf, + dst_x, + dst_y, + dst_w, + dst_h, + This->l_pitch, + src_buf, + src_x, + src_y, + src_surface->l_pitch, + This->bpp); } } @@ -960,8 +513,8 @@ HRESULT dds_GetSurfaceDesc(IDirectDrawSurfaceImpl* This, LPDDSURFACEDESC lpDDSur } HRESULT dds_EnumAttachedSurfaces( - IDirectDrawSurfaceImpl* This, - LPVOID lpContext, + IDirectDrawSurfaceImpl* This, + LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) { static DDSURFACEDESC2 desc; @@ -1163,10 +716,10 @@ HRESULT dds_GetPixelFormat(IDirectDrawSurfaceImpl* This, LPDDPIXELFORMAT ddpfPix } HRESULT dds_Lock( - IDirectDrawSurfaceImpl* This, - LPRECT lpDestRect, - LPDDSURFACEDESC lpDDSurfaceDesc, - DWORD dwFlags, + IDirectDrawSurfaceImpl* This, + LPRECT lpDestRect, + LPDDSURFACEDESC lpDDSurfaceDesc, + DWORD dwFlags, HANDLE hEvent) { dbg_dump_dds_lock_flags(dwFlags); @@ -1409,9 +962,9 @@ void* dds_GetBuffer(IDirectDrawSurfaceImpl* This) } HRESULT dd_CreateSurface( - IDirectDrawImpl* This, - LPDDSURFACEDESC lpDDSurfaceDesc, - IDirectDrawSurfaceImpl** lpDDSurface, + IDirectDrawImpl* This, + LPDDSURFACEDESC lpDDSurfaceDesc, + IDirectDrawSurfaceImpl** lpDDSurface, IUnknown FAR* unkOuter) { dbg_dump_dds_flags(lpDDSurfaceDesc->dwFlags); @@ -1429,7 +982,7 @@ HRESULT dd_CreateSurface( return DD_OK; } - IDirectDrawSurfaceImpl* dst_surface = + IDirectDrawSurfaceImpl* dst_surface = (IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawSurfaceImpl)); dst_surface->lpVtbl = &g_dds_vtbl; @@ -1490,7 +1043,7 @@ HRESULT dd_CreateSurface( } } - dst_surface->bmi = + dst_surface->bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256); dst_surface->bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); @@ -1507,7 +1060,7 @@ HRESULT dd_CreateSurface( dst_surface->bmi->bmiHeader.biClrUsed = (1 << clr_bits); } - dst_surface->bmi->bmiHeader.biSizeImage = + dst_surface->bmi->bmiHeader.biSizeImage = ((dst_surface->width * clr_bits + 31) & ~31) / 8 * dst_surface->height; if (dst_surface->bpp == 8) @@ -1534,7 +1087,7 @@ HRESULT dd_CreateSurface( } dst_surface->hdc = CreateCompatibleDC(g_ddraw->render.hdc); - dst_surface->bitmap = + dst_surface->bitmap = CreateDIBSection(dst_surface->hdc, dst_surface->bmi, DIB_RGB_COLORS, (void**)&dst_surface->surface, NULL, 0); dst_surface->bmi->bmiHeader.biHeight = -((int)dst_surface->height); @@ -1579,10 +1132,10 @@ HRESULT dd_CreateSurface( } TRACE( - " surface = %p (%ux%u@%u)\n", - dst_surface, - dst_surface->width, - dst_surface->height, + " surface = %p (%ux%u@%u)\n", + dst_surface, + dst_surface->width, + dst_surface->height, dst_surface->bpp); *lpDDSurface = dst_surface; diff --git a/src/render_d3d9.c b/src/render_d3d9.c index 9a267b4..5915280 100644 --- a/src/render_d3d9.c +++ b/src/render_d3d9.c @@ -8,6 +8,7 @@ #include "render_d3d9.h" #include "utils.h" #include "wndproc.h" +#include "blt.h" #include "debug.h" @@ -388,17 +389,18 @@ DWORD WINAPI d3d9_render_main(void) if (SUCCEEDED(IDirect3DDevice9_SetTexture(g_d3d9.device, 0, (IDirect3DBaseTexture9*)g_d3d9.surface_tex[tex_index])) && SUCCEEDED(IDirect3DTexture9_LockRect(g_d3d9.surface_tex[tex_index], 0, &lock_rc, &rc, 0))) { - unsigned char* src = (unsigned char*)g_ddraw->primary->surface; - unsigned char* dst = (unsigned char*)lock_rc.pBits; - - int i; - for (i = 0; i < g_ddraw->height; i++) - { - memcpy(dst, src, g_ddraw->primary->l_pitch); - - src += g_ddraw->primary->l_pitch; - dst += lock_rc.Pitch; - } + blt_clean( + lock_rc.pBits, + 0, + 0, + min(g_ddraw->width, g_ddraw->primary->width), + min(g_ddraw->height, g_ddraw->primary->height), + lock_rc.Pitch, + g_ddraw->primary->surface, + 0, + 0, + g_ddraw->primary->l_pitch, + g_ddraw->primary->bpp); IDirect3DTexture9_UnlockRect(g_d3d9.surface_tex[tex_index], 0); }