c++ SDL使用SDL_TEXTUREACCESS_STREAMING传输纹理

toe95027  于 2023-08-09  发布在  其他
关注(0)|答案(1)|浏览(166)

我正在使用SDL 2和SDL_TEXTUREACCESS_STREAMING,而没有OpenGL,我想将一些纹理从我的函数转移/组合到我的主循环中。因此,我决定将我的访问类型从STREAMING更改为TARGET,使用SDL_SetRenderTargetSDL_RenderCopy,并再次将访问类型设置为STREAMING,但当我使用SDL_RenderPresent预览时,没有显示发送的纹理。
下面是我打开纹理的函数:

TUserFunc(
    void, OpenTTF, Reference font, int32_t align, int32_t x, int32_t y, Reference txt, int32_t scl)
{    
    int tgt_w = g_w;
    int tgt_h = g_h; 
 
    TTF_Font * ttfFont = TTF_OpenFont(pu->refToAstr(CP_THREAD_ACP, font).c_str(), scl);
    if(ttfFont == nullptr) { 
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error cargando la direccion de las fuentes", NULL);
        quitGame();
    } 
    
    SDL_Surface * surfaceText = TTF_RenderText_Blended(ttfFont, (pu->refToAstr(CP_THREAD_ACP, txt).c_str()), color);
    if(surfaceText == nullptr){
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error creando Superficie", NULL);
        quitGame();
    } 
    
    textureText = SDL_CreateTextureFromSurface(g_renderer,surfaceText); 
    if(textureText == nullptr){
        SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error creando Texturas", NULL);
        quitGame();
    } 

    SDL_Rect rectangle;
    rectangle.x = x;
    rectangle.y = y;
    rectangle.w = surfaceText->w;
    rectangle.h = surfaceText->h;

//The Problem Start from here

    unlockTarget(); 
    g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, tgt_w, tgt_h);

    SDL_SetRenderTarget(g_renderer, g_target);
    SDL_RenderCopy(g_renderer, textureText, NULL, &rectangle);
    SDL_SetRenderTarget(g_renderer, NULL);
     
    g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, tgt_w, tgt_h);
    lockTarget();
}

字符串
lockTarget()unlockTarget()这是一个简单的方法来锁定和解锁纹理,你可以看到,我使用CreateTexture更改为TARGET,把我的SetRenderTargetRenderCopy,并再次使用CreateTexture更改回STREAMING
这是我的主要循环来显示图形:

TUserFunc(void, Flip)
{       

    if(g_target){
        unlockTarget();
        SDL_RenderCopy(g_renderer, g_target, nullptr, nullptr); 
        lockTarget();
    }     
    SDL_RenderPresent(g_renderer);
}


但是如果我加上这个,纹理会显示出来,但不是相同的纹理,我的意思是,不是和g_target结合在一起

TUserFunc(void, Flip)
{       

    if(g_target){
        unlockTarget();
        SDL_RenderCopy(g_renderer, g_target, nullptr, nullptr); 
        lockTarget();
    }    
    if(textureText){
        unlockTarget();
        SDL_RenderCopy(g_renderer, textureText, nullptr, nullptr); 
        lockTarget();
    }
    SDL_RenderPresent(g_renderer);
}


在这里,您可以看到其他函数,以便更好地了解问题:

TUserFunc(bool, Init...)
{
...
        // This is the main and unique call to g_target
    g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888,
            SDL_TEXTUREACCESS_STREAMING, w, h);
    SDL_SetTextureBlendMode(g_target, SDL_BLENDMODE_NONE);
...
}

void lockTarget()
{
    if(g_target) SDL_LockTexture(g_target, nullptr, (void**)&g_pix, &g_pitch);
    if(textureText) SDL_LockTexture(textureText, nullptr, (void**)&g_pix, &g_pitch);
}

void unlockTarget()
{
    if(g_target) SDL_UnlockTexture(g_target);
    if(textureText) SDL_UnlockTexture(textureText);
}

eqoofvh9

eqoofvh91#

问题是

这行不通:

unlockTarget(); 
g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, tgt_w, tgt_h);

SDL_SetRenderTarget(g_renderer, g_target);
SDL_RenderCopy(g_renderer, textureText, NULL, &rectangle);
SDL_SetRenderTarget(g_renderer, NULL);
 
g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, tgt_w, tgt_h);
lockTarget();

字符串
创建一个纹理,在其上渲染另一个纹理,然后继续删除其指针并创建一个新的纹理。
SDL_CreateTexture,顾名思义,创建纹理。
使用这一行:

g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, tgt_w, tgt_h);


你实际上是扔掉了g_target所持有的任何东西,并用一个新的、空的、具有STREAMING访问权限的纹理来替换它。
我使用CreateTexture更改为TARGET,将我的SetRenderTargetRenderCopy放在一起,然后再次使用CreateTexture更改回STREAMING
这根本不是它的工作方式。一旦创建纹理,就不能更改其访问模式。SDL_CreateTexture所做的只是创建另一个纹理。
因此,您所做的一切就是泄漏内存并获得无法工作的代码。

clean解决方案

根据the documentationarchive),SDL_Texture是:
一种结构,它包含像素数据的有效的、驱动程序特定的表示形式。
你不应该做任何事情SDL_Texture s除了渲染他们或渲染其他纹理到它。无法真实的更改其访问模式。
如果你真的需要在其他纹理之上渲染纹理,然后访问它们的像素数据,那么使用SDL_Surface s(archive):
一种包含用于软件位块传送的像素集合的结构。
您也可以使用SDL_BlitSurface将它们blit在其他对象之上。此外,您还可以访问SDL_Surface s的像素数据以进行进一步编辑。
只有当你接触到像素数据时,才能使用SDL_CreateTextureFromSurface将其转换为纹理并渲染它。
这可能比直接处理纹理要慢,但至少它是有效的,而且应该这样做。
当然,STREAMING模式存在于纹理上是有原因的,但是你所能做的就是用它来做一些不好的事情,而使用表面会更好。
除此之外,你不能像我已经说过的那样将纹理的访问模式从TARGET更改为STREAMING,所以你在这里没有选择。你需要使用曲面。

相关问题