SDL2中SDL_TEXTUREACCESS_STREAMING纹理合并显示异常求助
问题分析与解决方案
核心问题
- 纹理数据完全丢失:你每次重建
g_target时都是创建全新的空纹理,既没有继承原有STREAMING纹理的像素数据,也没有保留刚绘制的文字内容,最终渲染的是空白纹理。 lockTarget函数指针冲突:g_pix被连续两次赋值,原g_target的像素指针会被textureText的指针覆盖,导致无法正确操作目标纹理的像素,还可能引发内存泄漏。- 不必要的纹理重建:SDL纹理的访问类型是创建时确定的,不需要反复销毁重建,通过中间纹理或直接像素复制即可完成合并。
解决方案1:用临时目标纹理合并后复制回STREAMING纹理
保留原g_target的STREAMING类型,通过临时TARGET纹理完成文字与原纹理的合并,再将结果复制回g_target:
修改OpenTTF函数的问题代码段:
// 问题从此处开始 unlockTarget(); // 1. 创建临时目标纹理 SDL_Texture* temp_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, tgt_w, tgt_h); if (!temp_target) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error creating temp target", NULL); quitGame(); } // 2. 将原g_target内容复制到临时目标 SDL_SetRenderTarget(g_renderer, temp_target); SDL_RenderCopy(g_renderer, g_target, nullptr, nullptr); // 3. 绘制文字到临时目标 SDL_RenderCopy(g_renderer, textureText, NULL, &rectangle); SDL_SetRenderTarget(g_renderer, NULL); // 4. 把临时目标的像素复制回g_target void* temp_pixels; int temp_pitch; SDL_LockTexture(temp_target, nullptr, &temp_pixels, &temp_pitch); SDL_LockTexture(g_target, nullptr, (void**)&g_pix, &g_pitch); // 像素格式匹配(ARGB8888),直接内存复制 memcpy(g_pix, temp_pixels, tgt_w * tgt_h * 4); SDL_UnlockTexture(g_target); SDL_UnlockTexture(temp_target); // 清理临时资源 SDL_DestroyTexture(temp_target); lockTarget();
同时修正lockTarget函数,避免指针覆盖:
// 新增全局变量存储各自的像素指针和行距 void* g_pix_target = nullptr; int g_pitch_target = 0; void* g_pix_text = nullptr; int g_pitch_text = 0; void lockTarget() { if(g_target) SDL_LockTexture(g_target, nullptr, (void**)&g_pix_target, &g_pitch_target); if(textureText) SDL_LockTexture(textureText, nullptr, (void**)&g_pix_text, &g_pitch_text); } void unlockTarget() { if(g_target) SDL_UnlockTexture(g_target); if(textureText) SDL_UnlockTexture(textureText); }
解决方案2:直接将文字Surface像素复制到STREAMING纹理
跳过渲染目标,直接操作像素缓冲区完成合并,效率更高:
修改OpenTTF函数的问题代码段:
// 问题从此处开始 unlockTarget(); // 锁定g_target获取像素指针 void* target_pixels; int target_pitch; SDL_LockTexture(g_target, nullptr, &target_pixels, &target_pitch); // 转换为像素数组(ARGB8888格式) uint32_t* src_pixels = (uint32_t*)surfaceText->pixels; uint32_t* dst_pixels = (uint32_t*)target_pixels; int src_pitch_div = surfaceText->pitch / 4; int dst_pitch_div = target_pitch / 4; // 逐像素复制文字到目标纹理对应位置 for (int y = 0; y < surfaceText->h; y++) { for (int x = 0; x < surfaceText->w; x++) { int dst_x = x + rectangle.x; int dst_y = y + rectangle.y; // 确保坐标不越界 if (dst_x >= 0 && dst_x < tgt_w && dst_y >= 0 && dst_y < tgt_h) { dst_pixels[dst_y * dst_pitch_div + dst_x] = src_pixels[y * src_pitch_div + x]; } } } SDL_UnlockTexture(g_target); lockTarget(); // 清理临时资源(避免内存泄漏) SDL_FreeSurface(surfaceText); SDL_DestroyTexture(textureText); textureText = nullptr;
额外注意事项
- 每次创建
textureText后,记得在不需要时销毁,避免内存泄漏。 - 确保所有纹理/表面的像素格式一致(此处为ARGB8888),否则需要添加格式转换逻辑。
- 如果需要alpha混合效果,需设置正确的纹理混合模式,或手动处理像素的alpha通道。
内容的提问来源于stack exchange,提问作者Strong FS - MUGEN Studio
相关产品推荐
相关产品推荐

