首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SDL2访问渲染帧缓冲区

SDL2访问渲染帧缓冲区
EN

Stack Overflow用户
提问于 2020-02-11 17:09:07
回答 1查看 1.6K关注 0票数 0

我试图以Uint32*像素数组的形式访问SDL_Renderer的帧缓冲区,以传递给Libretro的显示函数。

我创建了这个最小的示例,以展示我在网上看到的两种访问SDL的帧缓冲区的方法,这两种方法都不起作用。

代码语言:javascript
复制
#include <iostream>
#include "SDL.h"

const int WIDTH = 50;
const int HEIGHT = 40;
int frameIndex = 0;

int main(int argc, char *argv[]) {
    SDL_Init(SDL_INIT_VIDEO);

    auto win = SDL_CreateWindow("Framebuffer test", SDL_WINDOWPOS_CENTERED | SDL_WINDOW_OPENGL, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);

    auto renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);

    auto pixels = new uint32_t[WIDTH * HEIGHT]; // width x height x SDL_PIXELFORMAT_RGBA8888
    auto surface = SDL_CreateRGBSurface(SDL_WINDOW_SHOWN, WIDTH, HEIGHT, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);

    // Rect to draw on the screen
    SDL_Rect rect;
    rect.x = 0;
    rect.y = 0;
    rect.w = 10;
    rect.h = 10;

    while (true) {
        SDL_Event e;
        if (SDL_PollEvent(&e)) {
            if (e.type == SDL_QUIT) {
                break;
            }
        }

        SDL_RenderClear(renderer);

        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
        SDL_RenderDrawRect(renderer, &rect);
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

        // Access framebuffer: method 1
        SDL_RenderReadPixels(renderer, nullptr, SDL_PIXELFORMAT_ARGB8888, pixels, 1);
        auto surfacePixels = (Uint32*) surface->pixels;
        for (int i = 0; i < WIDTH * HEIGHT; ++i)
            surfacePixels[i] = pixels[i];
        SDL_LockSurface(surface);
        SDL_SaveBMP(surface, ("screen1_" + std::to_string(frameIndex) + ".bmp").c_str()); // Output buffer
        SDL_UnlockSurface(surface);

        // Access frame buffer: method 2
        auto surf = SDL_GetWindowSurface(win);
        SDL_LockSurface(surf);
        SDL_SaveBMP(surf, ("screen2_" + std::to_string(frameIndex) + ".bmp").c_str()); // Output buffer
        SDL_UnlockSurface(surf);
        std::cout << "Screenshot: " << frameIndex++ << std::endl;

        SDL_RenderPresent(renderer);

        if (frameIndex >= 20)
            break;
    }

    SDL_FreeSurface(surface);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);

    SDL_Quit();

    return 0;
}

窗口/所需输出

方法1结果

方法2结果

我期望看到一个带有白色方块的黑屏,但在第一种方法中我看到的是噪声,在第二种方法中我看到的是黑屏。我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-11 17:43:22

您的SDL_RenderReadPixels间距参数是1。间距是单个图像行的字节长度。如果每个像素是4个字节宽,每行是1个字节...图像是1/4像素宽吗?听起来很有问题。正确的间距是4 * WIDTH (加上填充,但你没有32位格式)。

其他备注:

SDL_CreateRGBSurface的第一个参数是“标志-标志未使用,应设置为0",而不是SDL_WINDOW_SHOWN。不会改变任何东西,因为它被忽略了,但它至少是误导性的。

如果存在与窗口关联的渲染器,则无法使用SDL_GetWindowSurface。文档中写道:“您不能将其与3D或此窗口上的渲染API结合使用”。

SDL_LockSurface应该在访问表面像素之前,解锁之后。在大多数表面上不需要锁定,所以您看不到任何不同之处,但是在SaveBMP之前锁定在逻辑上是不正确的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60165231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档