Skip to content

Commit 61822d4

Browse files
committed
cellGem: fix RAW8 to RGBA_320x240
We were basically writing two rows into dst for each other src line. This means we were writing 480 lines in total instead of 240, overwriting one of the lines written in the previous iteration. This led to writing one line out of bounds last iteration. Let's just use a simple debayer technique which perfectly matches here. This also applies the previously missing gain factors. I also tried to first demosaic and then drop every other pixel. The result was comparatively blurred and the performance worse.
1 parent d6a4b59 commit 61822d4

1 file changed

Lines changed: 48 additions & 28 deletions

File tree

rpcs3/Emu/Cell/Modules/cellGem.cpp

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,53 @@ namespace gem
845845
debayer_raw8_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
846846
}
847847

848+
template <bool use_gain>
849+
static inline void debayer_raw8_downscale_impl(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
850+
{
851+
constexpr u32 in_pitch = 640;
852+
constexpr u32 out_pitch = 320 * 4;
853+
854+
// Simple debayer
855+
for (s32 y = 0; y < 240; y++)
856+
{
857+
const u8* src0 = src + y * 2 * in_pitch;
858+
const u8* src1 = src0 + in_pitch;
859+
860+
u8* dst0 = dst + y * out_pitch;
861+
862+
for (s32 x = 0; x < 320; x++, dst0 += 4, src0 += 2, src1 += 2)
863+
{
864+
const u8 b = src0[0];
865+
const u8 g0 = src0[1];
866+
const u8 g1 = src1[0];
867+
const u8 r = src1[1];
868+
const u8 g = (g0 + g1) >> 1;
869+
870+
if constexpr (use_gain)
871+
{
872+
dst0[0] = static_cast<u8>(std::clamp(r * gain_r, 0.0f, 255.0f));
873+
dst0[1] = static_cast<u8>(std::clamp(g * gain_g, 0.0f, 255.0f));
874+
dst0[2] = static_cast<u8>(std::clamp(b * gain_b, 0.0f, 255.0f));
875+
}
876+
else
877+
{
878+
dst0[0] = r;
879+
dst0[1] = g;
880+
dst0[2] = b;
881+
}
882+
dst0[3] = alpha;
883+
}
884+
}
885+
}
886+
887+
static void debayer_raw8_downscale(const u8* src, u8* dst, u8 alpha, f32 gain_r, f32 gain_g, f32 gain_b)
888+
{
889+
if (gain_r != 1.0f || gain_g != 1.0f || gain_b != 1.0f)
890+
debayer_raw8_downscale_impl<true>(src, dst, alpha, gain_r, gain_g, gain_b);
891+
else
892+
debayer_raw8_downscale_impl<false>(src, dst, alpha, gain_r, gain_g, gain_b);
893+
}
894+
848895
bool convert_image_format(CellCameraFormat input_format, const CellGemVideoConvertAttribute& vc,
849896
const std::vector<u8>& video_data_in, u32 width, u32 height,
850897
u8* video_data_out, u32 video_data_out_size, u8* buffer_memory,
@@ -1183,34 +1230,7 @@ namespace gem
11831230
{
11841231
case CELL_CAMERA_RAW8:
11851232
{
1186-
const u32 in_pitch = width;
1187-
const u32 out_pitch = width * 4 / 2;
1188-
1189-
for (u32 y = 0; y < height - 1; y += 2)
1190-
{
1191-
const u8* src0 = src_data + y * in_pitch;
1192-
const u8* src1 = src0 + in_pitch;
1193-
1194-
u8* dst0 = video_data_out + (y / 2) * out_pitch;
1195-
u8* dst1 = dst0 + out_pitch;
1196-
1197-
for (u32 x = 0; x < width - 1; x += 2, src0 += 2, src1 += 2, dst0 += 4, dst1 += 4)
1198-
{
1199-
const u8 b = src0[0];
1200-
const u8 g0 = src0[1];
1201-
const u8 g1 = src1[0];
1202-
const u8 r = src1[1];
1203-
1204-
const u8 top[4] = { r, g0, b, alpha };
1205-
const u8 bottom[4] = { r, g1, b, alpha };
1206-
1207-
// Top-Left
1208-
std::memcpy(dst0, top, 4);
1209-
1210-
// Bottom-Left Pixel
1211-
std::memcpy(dst1, bottom, 4);
1212-
}
1213-
}
1233+
debayer_raw8_downscale(src_data, video_data_out, alpha, gain_r, gain_g, gain_b);
12141234
break;
12151235
}
12161236
case CELL_CAMERA_RGBA:

0 commit comments

Comments
 (0)