RSDKModding / RSDKv3-Decompilation

A Full Decompilation of Sonic CD (2011) & Retro Engine (v3)
Other
591 stars 121 forks source link

Use SDL_UpdateTexture instead of do the copy manually #211

Closed fjtrujy closed 1 year ago

fjtrujy commented 1 year ago

Description

Making use of the SDL_UpdateTexture for do the copy texture content properly.

Previously you were doing:

memcpy(pixels, Engine.frameBuffer, pitch * SCREEN_YSIZE); //faster but produces issues with odd numbered screen sizes

However as the comment said, that it is faster, but was producing some errors with "odd numbered screen sizes", this is because some devices have some requirements when rendering textures, as for instance, texture must be 128 bits multiples (as PSP has).

Then, this is why you decided to use the pitch and start copying line by line.

SDL_LockTexture(Engine.screenBuffer, NULL, (void **)&pixels, &pitch);
ushort *frameBufferPtr = Engine.frameBuffer;
for (int y = 0; y < SCREEN_YSIZE; ++y) {
    memcpy(pixels, frameBufferPtr, SCREEN_XSIZE * sizeof(ushort));
    frameBufferPtr += GFX_LINESIZE;
    pixels += pitch / sizeof(ushort);
}

With that implementation you are "safer" but slower, so the proper implementation would be something like:

SDL_LockTexture(Engine.screenBuffer, NULL, (void **)&pixels, &pitch);
ushort *frameBufferPtr = Engine.frameBuffer;
if (pitch != GFX_LINESIZE * sizeof(ushort)) {
    for (int y = 0; y < SCREEN_YSIZE; ++y) {
        memcpy(pixels, frameBufferPtr, SCREEN_XSIZE * sizeof(ushort));
        frameBufferPtr += GFX_LINESIZE;
        pixels += pitch / sizeof(ushort);
    }
} else {
    memcpy(pixels, Engine.frameBuffer, pitch * SCREEN_YSIZE); //faster but produces issues with odd numbered screen sizes
}
SDL_UnlockTexture(Engine.screenBuffer);

In this way, just these devices where the texture resolution requires to have some additional pitch will use the slow way, and the rest will use the fast way.

So, all this piece of code is what actually the SDL_UpdateTexture function is doing:

SDL_UpdateTexture(Engine.screenBuffer, NULL, (void *)Engine.frameBuffer, GFX_LINESIZE * sizeof(ushort));

Cheers!