Direct3D11: Fix screenshots being corrupted, instead now Red and Blue are swapped

This commit is contained in:
UnknownShadow200 2021-09-25 09:02:50 +10:00
parent 21faabba3e
commit e413f763ad
5 changed files with 30 additions and 19 deletions

View file

@ -625,9 +625,9 @@ static void Png_EncodeRow(const cc_uint8* cur, const cc_uint8* prior, cc_uint8*
best[0] = bestFilter;
}
static int Png_SelectRow(struct Bitmap* bmp, int y) { return y; }
static BitmapCol* DefaultGetRow(struct Bitmap* bmp, int y) { return Bitmap_GetRow(bmp, y); }
cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream,
Png_RowSelector selectRow, cc_bool alpha) {
Png_RowGetter getRow, cc_bool alpha) {
cc_uint8 tmp[32];
/* TODO: This should be * 4 for alpha (should switch to mem_alloc though) */
cc_uint8 prevLine[PNG_MAX_DIMS * 3], curLine[PNG_MAX_DIMS * 3];
@ -642,7 +642,7 @@ cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream,
/* stream may not start at 0 (e.g. when making default.zip) */
if ((res = stream->Position(stream, &stream_beg))) return res;
if (!selectRow) selectRow = Png_SelectRow;
if (!getRow) getRow = DefaultGetRow;
if ((res = Stream_Write(stream, pngSig, PNG_SIG_SIZE))) return res;
Stream_WriteonlyCrc32(&chunk, stream);
@ -671,8 +671,7 @@ cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream,
Mem_Set(prevLine, 0, lineSize);
for (y = 0; y < bmp->height; y++) {
int row = selectRow(bmp, y);
BitmapCol* src = Bitmap_GetRow(bmp, row);
BitmapCol* src = getRow(bmp, y);
cc_uint8* prev = (y & 1) == 0 ? prevLine : curLine;
cc_uint8* cur = (y & 1) == 0 ? curLine : prevLine;

View file

@ -79,7 +79,7 @@ CC_API void Bitmap_Scale(struct Bitmap* dst, struct Bitmap* src,
/* Whether data starts with PNG format signature/identifier. */
cc_bool Png_Detect(const cc_uint8* data, cc_uint32 len);
typedef int (*Png_RowSelector)(struct Bitmap* bmp, int row);
typedef BitmapCol* (*Png_RowGetter)(struct Bitmap* bmp, int row);
/*
Decodes a bitmap in PNG format. Partially based off information from
https://handmade.network/forums/wip/t/2363-implementing_a_basic_png_reader_the_handmade_way
@ -87,8 +87,8 @@ typedef int (*Png_RowSelector)(struct Bitmap* bmp, int row);
*/
CC_API cc_result Png_Decode(struct Bitmap* bmp, struct Stream* stream);
/* Encodes a bitmap in PNG format. */
/* selectRow is optional. Can be used to modify how rows are encoded. (e.g. flip image) */
/* getRow is optional. Can be used to modify how rows are encoded. (e.g. flip image) */
/* if alpha is non-zero, RGBA channels are saved, otherwise only RGB channels are. */
CC_API cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream,
Png_RowSelector selectRow, cc_bool alpha);
cc_result Png_Encode(struct Bitmap* bmp, struct Stream* stream,
Png_RowGetter getRow, cc_bool alpha);
#endif

View file

@ -706,6 +706,17 @@ void Gfx_SetColWriteMask(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
/*########################################################################################################################*
*-----------------------------------------------------------Misc----------------------------------------------------------*
*#########################################################################################################################*/
static BitmapCol* D3D11_GetRow(struct Bitmap* bmp, int y) {
// You were expecting a BitmapCol*, but it was me, D3D11_MAPPED_SUBRESOURCE*!
// This is necessary because the stride of the mapped backbuffer often doesn't equal width of the bitmap
// e.g. with backbuffer width of 854, stride is 3456 bytes instead of expected 3416 (854*4)
// Therefore have to calculate row address manually instead of using Bitmap_GetRow
D3D11_MAPPED_SUBRESOURCE* buffer = (D3D11_MAPPED_SUBRESOURCE*)bmp->scan0;
char* row = (char*)buffer->pData + y * buffer->RowPitch;
return (BitmapCol*)row;
}
cc_result Gfx_TakeScreenshot(struct Stream* output) {
ID3D11Texture2D* tmp;
struct Bitmap bmp;
@ -734,8 +745,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
hr = ID3D11DeviceContext_Map(context, tmp, 0, D3D11_MAP_READ, 0, &buffer);
if (hr) goto finished;
{
Bitmap_Init(bmp, desc.Width, desc.Height, (BitmapCol*)buffer.pData);
hr = Png_Encode(&bmp, output, NULL, false);
Bitmap_Init(bmp, desc.Width, desc.Height, (BitmapCol*)&buffer);
hr = Png_Encode(&bmp, output, D3D11_GetRow, false);
}
ID3D11DeviceContext_Unmap(context, tmp, 0);
@ -757,7 +768,6 @@ void Gfx_EndFrame(void) {
if (hr) Logger_Abort2(hr, "Failed to swap buffers");
}
// you were expecting a BitmapCol*, but it was me, D3D11_MAPPED_SUBRESOURCE*!
cc_bool Gfx_WarnIfNecessary(void) { return false; }
void Gfx_GetApiInfo(cc_string* info) {

View file

@ -430,8 +430,10 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
/*########################################################################################################################*
*-----------------------------------------------------------Misc----------------------------------------------------------*
*#########################################################################################################################*/
/* OpenGL stores bitmap in bottom-up order, so flip order when saving */
static int SelectRow(struct Bitmap* bmp, int y) { return (bmp->height - 1) - y; }
static BitmapCol* GL_GetRow(struct Bitmap* bmp, int y) {
/* OpenGL stores bitmap in bottom-up order, so flip order when saving */
return Bitmap_GetRow(bmp, (bmp->height - 1) - y);
}
cc_result Gfx_TakeScreenshot(struct Stream* output) {
struct Bitmap bmp;
cc_result res;
@ -445,7 +447,7 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) {
if (!bmp.scan0) return ERR_OUT_OF_MEMORY;
glReadPixels(0, 0, bmp.width, bmp.height, PIXEL_FORMAT, TRANSFER_FORMAT, bmp.scan0);
res = Png_Encode(&bmp, output, SelectRow, false);
res = Png_Encode(&bmp, output, GL_GetRow, false);
Mem_Free(bmp.scan0);
return res;
}

View file

@ -74,8 +74,8 @@ static int RunProgram(int argc, char** argv) {
#ifdef _MSC_VER
/* NOTE: Make sure to comment this out before pushing a commit */
//cc_string rawArgs = String_FromConst("UnknownShadow200 fffff 127.0.0.1 25565");
cc_string rawArgs = String_FromConst("UnknownShadow200");
argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
//cc_string rawArgs = String_FromConst("UnknownShadow200");
//argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
#endif
if (argsCount == 0) {