Add SDL_UpdateNVTexture() to update NV12/21 Texture (bug #5430)

for renderer software, opengl, and opengles2
This commit is contained in:
Sylvain Becker 2021-01-05 11:56:22 +01:00
parent d72dbd9883
commit be4cfd51c3
7 changed files with 254 additions and 0 deletions

View file

@ -1628,6 +1628,59 @@ SDL_UpdateTextureYUVPlanar(SDL_Texture * texture, const SDL_Rect * rect,
}
return 0;
}
static int
SDL_UpdateTextureNVPlanar(SDL_Texture * texture, const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *UVplane, int UVpitch)
{
SDL_Texture *native = texture->native;
SDL_Rect full_rect;
if (SDL_SW_UpdateNVTexturePlanar(texture->yuv, rect, Yplane, Ypitch, UVplane, UVpitch) < 0) {
return -1;
}
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
full_rect.h = texture->h;
rect = &full_rect;
if (!rect->w || !rect->h) {
return 0; /* nothing to do. */
}
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
/* We can lock the texture and copy to it */
void *native_pixels = NULL;
int native_pitch = 0;
if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
return -1;
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, native_pixels, native_pitch);
SDL_UnlockTexture(native);
} else {
/* Use a temporary buffer for updating */
const int temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
const size_t alloclen = rect->h * temp_pitch;
if (alloclen > 0) {
void *temp_pixels = SDL_malloc(alloclen);
if (!temp_pixels) {
return SDL_OutOfMemory();
}
SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
rect->w, rect->h, temp_pixels, temp_pitch);
SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
SDL_free(temp_pixels);
}
}
return 0;
}
#endif /* SDL_HAVE_YUV */
int SDL_UpdateYUVTexture(SDL_Texture * texture, const SDL_Rect * rect,
@ -1697,6 +1750,68 @@ int SDL_UpdateYUVTexture(SDL_Texture * texture, const SDL_Rect * rect,
#endif
}
int SDL_UpdateNVTexture(SDL_Texture * texture, const SDL_Rect * rect,
const Uint8 *Yplane, int Ypitch,
const Uint8 *UVplane, int UVpitch)
{
#if SDL_HAVE_YUV
SDL_Renderer *renderer;
SDL_Rect full_rect;
CHECK_TEXTURE_MAGIC(texture, -1);
if (!Yplane) {
return SDL_InvalidParamError("Yplane");
}
if (!Ypitch) {
return SDL_InvalidParamError("Ypitch");
}
if (!UVplane) {
return SDL_InvalidParamError("UVplane");
}
if (!UVpitch) {
return SDL_InvalidParamError("UVpitch");
}
if (texture->format != SDL_PIXELFORMAT_NV12 &&
texture->format != SDL_PIXELFORMAT_NV21) {
return SDL_SetError("Texture format must by NV12 or NV21");
}
if (!rect) {
full_rect.x = 0;
full_rect.y = 0;
full_rect.w = texture->w;
full_rect.h = texture->h;
rect = &full_rect;
}
if (!rect->w || !rect->h) {
return 0; /* nothing to do. */
}
if (texture->yuv) {
return SDL_UpdateTextureNVPlanar(texture, rect, Yplane, Ypitch, UVplane, UVpitch);
} else {
SDL_assert(!texture->native);
renderer = texture->renderer;
SDL_assert(renderer->UpdateTextureNV);
if (renderer->UpdateTextureNV) {
if (FlushRenderCommandsIfTextureNeeded(texture) < 0) {
return -1;
}
return renderer->UpdateTextureNV(renderer, texture, rect, Yplane, Ypitch, UVplane, UVpitch);
} else {
return SDL_Unsupported();
}
}
#else
return -1;
#endif
}
#if SDL_HAVE_YUV
static int
SDL_LockTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,