Question

Background

I am working on a rendering client that draws graphical information it receives from a server. The server sends packets containing non-overlapping rectangles with different solid colors at a frame rate variably defined on the server. I currently have it configured so that the size of the screen being transmitted by the server is different than the size of the window onto which the client is drawing, so scaling is done. I need the client to draw these rectangles as quickly as possible to not fall behind the server's stream.

Currently, I am using SDL 2.0. I am using the streaming texture technique described in the SDL 2 Migration Guide to draw the rectangles onto an SDL_Surface. When the time to display a frame arrives, I calll SDL_UpdateTexture() to overwrite the pixel data for an SDL_Texture, and then I use SDL_RenderCopyEx() to copy the texture to the renderer. I need this function instead of SDL_RenderCopy() so I can specify SDL_FLIP_VERTICAL to account for the fact that the coordinates passed are bitmap-style.


Question

My current approach does not render the rectangles quickly enough. To get the client to be able to keep up with the server, I currently have to reduce the server's upload rate from 30+ FPS to 15- FPS. Even then, I have to make the socket's buffer dangerously large, and I end up getting to watch the client's rendering slowly fall behind and eventually result in packet loss.

What is the fastest way to get SDL to render these rectangles? If I am currently using the fastest method, what other APIs would others recommend to make a client that can keep up?

I have included a stripped-down version of my source code so others can look for improvements/mistakes.


Technical Details

I am using C++11, MinGW32, and SDL2 with Eclipse Kepler CDT and GCC 4.8.2 on Window 7 64-bit.


Stripped Code

int main(int argc, char** args) {
    // omitted initialization code

    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow(
        "RTSC",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        windowWidth,
        windowHeight,
        SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
    );
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Surface* surface = SDL_CreateRGBSurface(
        0,
        sourceWidth,
        sourceHeight,
        24,
        0xFF << 16,
        0xFF << 8,
        0xFF,
        0
    );
    SDL_FillRect(surface, nullptr, 0);
    SDL_Texture* texture = SDL_CreateTexture(
        renderer,
        surface->format->format,
        SDL_TEXTUREACCESS_STREAMING,
        sourceWidth,
        sourceHeight
    );

    bool running {true};
    while (running) {
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    running = false;
                    break;
                case SDL_WINDOWEVENT:
                    switch (event.windowevent.event) {
                        case SDL_WINDOWEVENT_CLOSE:
                            running = false;
                            break;
                        default:
                            break;
                    }
                    break;
                default:
                    break;
            }
        }

        // omitted packet reception and interpretation code

        for (uint32_t i {0}; i < receivedRegions; ++i) {
            Region& region = regions[i];
            SDL_Rect rect {
                (int) region.x,
                (int) region.y,
                (int) region.width,
                (int) region.height
            };
            uint32_t color =
                (region.red << 16) +
                (region.green << 8) +
                region.blue;
            SDL_FillRect(surface, &rect, color);
        }

        // omitted logic for determining whether to present the frame

        SDL_RenderClear(renderer);
        SDL_UpdateTexture(texture, nullptr, surface->pixels, surface->pitch);
        SDL_RenderCopyEx(
            renderer,
            texture,
            nullptr,
            nullptr,
            0,
            nullptr,
            SDL_FLIP_VERTICAL
        );
        SDL_RenderPresent(renderer);
        SDL_FillRect(surface, nullptr, 0);
    }

    // omitted clean-up and return code
}

No correct solution

OTHER TIPS

This is embarassing. Because of earlier instrumentation I had done on my server, I assumed all the problem was with the SDL rendering client. However, it turns out the client slows only when the server does. It has nothing to do with SDL at all. Sorry.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top