diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index d40b67cd9f..9903bd1ffd 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -10,6 +10,7 @@ #include "Emu/SysCalls/lv2/sys_time.h" #include "Common/BufferUtils.h" +#include "rsx_utils.h" extern "C" { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 0cecb914ed..620d989d1f 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -226,92 +226,6 @@ namespace rsx void read(void *dst, u32 width, u32 height, u32 pitch); }; - template - void pad_texture(void* inputPixels, void* outputPixels, u16 inputWidth, u16 inputHeight, u16 outputWidth, u16 outputHeight) - { - T *src, *dst; - src = static_cast(inputPixels); - dst = static_cast(outputPixels); - - for (u16 h = 0; h < inputHeight; ++h) - { - const u32 padded_pos = h * outputWidth; - const u32 pos = h * inputWidth; - for (u16 w = 0; w < inputWidth; ++w) - { - dst[padded_pos + w] = src[pos + w]; - } - } - } - - /* Note: What the ps3 calls swizzling in this case is actually z-ordering / morton ordering of pixels - * - Input can be swizzled or linear, bool flag handles conversion to and from - * - It will handle any width and height that are a power of 2, square or non square - * Restriction: It has mixed results if the height or width is not a power of 2 - */ - template - void convert_linear_swizzle(void* inputPixels, void* outputPixels, u16 width, u16 height, bool inputIsSwizzled) - { - u32 log2width, log2height; - - log2width = log2(width); - log2height = log2(height); - - // Max mask possible for square texture - u32 x_mask = 0x55555555; - u32 y_mask = 0xAAAAAAAA; - - // We have to limit the masks to the lower of the two dimensions to allow for non-square textures - u32 limit_mask = (log2width < log2height) ? log2width : log2height; - // double the limit mask to account for bits in both x and y - limit_mask = 1 << (limit_mask << 1); - - //x_mask, bits above limit are 1's for x-carry - x_mask = (x_mask | ~(limit_mask - 1)); - //y_mask. bits above limit are 0'd, as we use a different method for y-carry over - y_mask = (y_mask & (limit_mask - 1)); - - u32 offs_y = 0; - u32 offs_x = 0; - u32 offs_x0 = 0; //total y-carry offset for x - u32 y_incr = limit_mask; - - T *src, *dst; - - if (!inputIsSwizzled) - { - for (int y = 0; y < height; ++y) - { - src = static_cast(inputPixels) + y*width; - dst = static_cast(outputPixels) + offs_y; - offs_x = offs_x0; - for (int x = 0; x < width; ++x) - { - dst[offs_x] = src[x]; - offs_x = (offs_x - x_mask) & x_mask; - } - offs_y = (offs_y - y_mask) & y_mask; - if (offs_y == 0) offs_x0 += y_incr; - } - } - else - { - for (int y = 0; y < height; ++y) - { - src = static_cast(inputPixels) + offs_y; - dst = static_cast(outputPixels) + y*width; - offs_x = offs_x0; - for (int x = 0; x < width; ++x) - { - dst[x] = src[offs_x]; - offs_x = (offs_x - x_mask) & x_mask; - } - offs_y = (offs_y - y_mask) & y_mask; - if (offs_y == 0) offs_x0 += y_incr; - } - } - } - struct surface_info { u8 log2height; diff --git a/rpcs3/Emu/RSX/rsx_utils.cpp b/rpcs3/Emu/RSX/rsx_utils.cpp new file mode 100644 index 0000000000..25a9b5ecf2 --- /dev/null +++ b/rpcs3/Emu/RSX/rsx_utils.cpp @@ -0,0 +1,45 @@ +#include "stdafx.h" +#include "rsx_utils.h" + +extern "C" +{ +#include "libswscale/swscale.h" +} + +namespace rsx +{ + void convert_scale_image(u8 *dst, AVPixelFormat dst_format, int dst_width, int dst_height, int dst_pitch, + const u8 *src, AVPixelFormat src_format, int src_width, int src_height, int src_pitch, int src_slice_h, bool bilinear) + { + std::unique_ptr sws(sws_getContext(src_width, src_height, src_format, + dst_width, dst_height, dst_format, bilinear ? SWS_FAST_BILINEAR : SWS_POINT, NULL, NULL, NULL), sws_freeContext); + + sws_scale(sws.get(), &src, &src_pitch, 0, src_slice_h, &dst, &dst_pitch); + } + + void convert_scale_image(std::unique_ptr& dst, AVPixelFormat dst_format, int dst_width, int dst_height, int dst_pitch, + const u8 *src, AVPixelFormat src_format, int src_width, int src_height, int src_pitch, int src_slice_h, bool bilinear) + { + dst.reset(new u8[dst_pitch * dst_height]); + convert_scale_image(dst.get(), dst_format, dst_width, dst_height, dst_pitch, + src, src_format, src_width, src_height, src_pitch, src_slice_h, bilinear); + } + + void clip_image(u8 *dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch) + { + for (int y = 0; y < clip_h; ++y) + { + u8 *dst_row = dst + y * dst_pitch; + const u8 *src_row = src + (y + clip_y) * src_pitch + clip_x * bpp; + + std::memmove(dst_row, src_row, clip_w * bpp); + } + } + + void clip_image(std::unique_ptr& dst, const u8 *src, + int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch) + { + dst.reset(new u8[clip_h * dst_pitch]); + clip_image(dst.get(), src, clip_x, clip_y, clip_w, clip_h, bpp, src_pitch, dst_pitch); + } +} diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h new file mode 100644 index 0000000000..33ad93be5f --- /dev/null +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -0,0 +1,104 @@ +#pragma once + +extern "C" +{ +#include +} + +namespace rsx +{ + template + void pad_texture(void* inputPixels, void* outputPixels, u16 inputWidth, u16 inputHeight, u16 outputWidth, u16 outputHeight) + { + T *src, *dst; + src = static_cast(inputPixels); + dst = static_cast(outputPixels); + + for (u16 h = 0; h < inputHeight; ++h) + { + const u32 padded_pos = h * outputWidth; + const u32 pos = h * inputWidth; + for (u16 w = 0; w < inputWidth; ++w) + { + dst[padded_pos + w] = src[pos + w]; + } + } + } + + /* Note: What the ps3 calls swizzling in this case is actually z-ordering / morton ordering of pixels + * - Input can be swizzled or linear, bool flag handles conversion to and from + * - It will handle any width and height that are a power of 2, square or non square + * Restriction: It has mixed results if the height or width is not a power of 2 + */ + template + void convert_linear_swizzle(void* inputPixels, void* outputPixels, u16 width, u16 height, bool inputIsSwizzled) + { + u32 log2width, log2height; + + log2width = log2(width); + log2height = log2(height); + + // Max mask possible for square texture + u32 x_mask = 0x55555555; + u32 y_mask = 0xAAAAAAAA; + + // We have to limit the masks to the lower of the two dimensions to allow for non-square textures + u32 limit_mask = (log2width < log2height) ? log2width : log2height; + // double the limit mask to account for bits in both x and y + limit_mask = 1 << (limit_mask << 1); + + //x_mask, bits above limit are 1's for x-carry + x_mask = (x_mask | ~(limit_mask - 1)); + //y_mask. bits above limit are 0'd, as we use a different method for y-carry over + y_mask = (y_mask & (limit_mask - 1)); + + u32 offs_y = 0; + u32 offs_x = 0; + u32 offs_x0 = 0; //total y-carry offset for x + u32 y_incr = limit_mask; + + T *src, *dst; + + if (!inputIsSwizzled) + { + for (int y = 0; y < height; ++y) + { + src = static_cast(inputPixels) + y*width; + dst = static_cast(outputPixels) + offs_y; + offs_x = offs_x0; + for (int x = 0; x < width; ++x) + { + dst[offs_x] = src[x]; + offs_x = (offs_x - x_mask) & x_mask; + } + offs_y = (offs_y - y_mask) & y_mask; + if (offs_y == 0) offs_x0 += y_incr; + } + } + else + { + for (int y = 0; y < height; ++y) + { + src = static_cast(inputPixels) + offs_y; + dst = static_cast(outputPixels) + y*width; + offs_x = offs_x0; + for (int x = 0; x < width; ++x) + { + dst[x] = src[offs_x]; + offs_x = (offs_x - x_mask) & x_mask; + } + offs_y = (offs_y - y_mask) & y_mask; + if (offs_y == 0) offs_x0 += y_incr; + } + } + } + + void convert_scale_image(u8 *dst, AVPixelFormat dst_format, int dst_width, int dst_height, int dst_pitch, + const u8 *src, AVPixelFormat src_format, int src_width, int src_height, int src_pitch, int src_slice_h, bool bilinear); + + void convert_scale_image(std::unique_ptr& dst, AVPixelFormat dst_format, int dst_width, int dst_height, int dst_pitch, + const u8 *src, AVPixelFormat src_format, int src_width, int src_height, int src_pitch, int src_slice_h, bool bilinear); + + void clip_image(u8 *dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch); + void clip_image(std::unique_ptr& dst, const u8 *src, int clip_x, int clip_y, int clip_w, int clip_h, int bpp, int src_pitch, int dst_pitch); +} diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index ddfa06f7bb..a9d013b1f7 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -129,6 +129,7 @@ + @@ -574,6 +575,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 30963300e8..c0cdafaaf1 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -927,6 +927,9 @@ Emu\GPU\RSX + + Emu\GPU\RSX + @@ -1773,5 +1776,8 @@ Utilities + + Emu\GPU\RSX + \ No newline at end of file