mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-08-02 21:48:57 +00:00
Added SDL_PIXELFORMAT_P408 and SDL_PIXELFORMAT_P416
This commit is contained in:
@@ -2518,8 +2518,10 @@ bool SDL_UpdateYUVTexture(SDL_Texture *texture, const SDL_Rect *rect,
|
||||
}
|
||||
|
||||
CHECK_PARAM(texture->format != SDL_PIXELFORMAT_YV12 &&
|
||||
texture->format != SDL_PIXELFORMAT_IYUV) {
|
||||
return SDL_SetError("Texture format must be YV12 or IYUV");
|
||||
texture->format != SDL_PIXELFORMAT_IYUV &&
|
||||
texture->format != SDL_PIXELFORMAT_P408 &&
|
||||
texture->format != SDL_PIXELFORMAT_P416) {
|
||||
return SDL_SetError("Texture format must be YV12, IYUV, P408, or P416");
|
||||
}
|
||||
|
||||
real_rect.x = 0;
|
||||
|
||||
@@ -35,6 +35,8 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(SDL_PixelFormat format, SDL_Colorspac
|
||||
switch (format) {
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
case SDL_PIXELFORMAT_YUY2:
|
||||
case SDL_PIXELFORMAT_UYVY:
|
||||
case SDL_PIXELFORMAT_YVYU:
|
||||
@@ -80,13 +82,21 @@ SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(SDL_PixelFormat format, SDL_Colorspac
|
||||
swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
|
||||
swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * ((h + 1) / 2);
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
swdata->pitches[0] = w * SDL_BYTESPERPIXEL(format);
|
||||
swdata->pitches[1] = swdata->pitches[0];
|
||||
swdata->pitches[2] = swdata->pitches[1];
|
||||
swdata->planes[0] = swdata->pixels;
|
||||
swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
|
||||
swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * h;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_YUY2:
|
||||
case SDL_PIXELFORMAT_UYVY:
|
||||
case SDL_PIXELFORMAT_YVYU:
|
||||
swdata->pitches[0] = ((w + 1) / 2) * 4;
|
||||
swdata->planes[0] = swdata->pixels;
|
||||
break;
|
||||
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
swdata->pitches[0] = w;
|
||||
@@ -119,7 +129,7 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect,
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
if (rect->x == 0 && rect->y == 0 &&
|
||||
rect->w == swdata->w && rect->h == swdata->h) {
|
||||
rect->w == swdata->w && rect->h == swdata->h && pitch == swdata->pitches[0]) {
|
||||
SDL_memcpy(swdata->pixels, pixels,
|
||||
(size_t)(swdata->h * swdata->w) + 2 * ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2));
|
||||
} else {
|
||||
@@ -161,6 +171,47 @@ bool SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
if (rect->x == 0 && rect->y == 0 &&
|
||||
rect->w == swdata->w && rect->h == swdata->h && pitch == swdata->pitches[0]) {
|
||||
SDL_memcpy(swdata->pixels, pixels, (size_t)(swdata->h * pitch * 3));
|
||||
} else {
|
||||
Uint8 *src, *dst;
|
||||
int row;
|
||||
size_t length;
|
||||
const int bpp = SDL_BYTESPERPIXEL(swdata->format);
|
||||
|
||||
// Copy the Y plane
|
||||
src = (Uint8 *)pixels;
|
||||
dst = swdata->pixels;
|
||||
dst += rect->y * swdata->pitches[0] + rect->x *bpp;
|
||||
length = rect->w * bpp;
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += pitch;
|
||||
dst += swdata->pitches[0];
|
||||
}
|
||||
|
||||
// Copy the next plane
|
||||
dst = swdata->pixels + swdata->h * swdata->pitches[0];
|
||||
dst += rect->y * swdata->pitches[1] + rect->x * bpp;
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += pitch;
|
||||
dst += swdata->pitches[1];
|
||||
}
|
||||
|
||||
// Copy the next plane
|
||||
dst = swdata->pixels + swdata->h * swdata->pitches[0] + swdata->h * swdata->pitches[1];
|
||||
dst += rect->y * swdata->pitches[2] + rect->x * bpp;
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += pitch;
|
||||
dst += swdata->pitches[2];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELFORMAT_YUY2:
|
||||
case SDL_PIXELFORMAT_UYVY:
|
||||
case SDL_PIXELFORMAT_YVYU:
|
||||
@@ -229,47 +280,72 @@ bool SDL_SW_UpdateYUVTexturePlanar(SDL_SW_YUVTexture *swdata, const SDL_Rect *re
|
||||
Uint8 *dst;
|
||||
int row;
|
||||
size_t length;
|
||||
const int bpp = SDL_BYTESPERPIXEL(swdata->format);
|
||||
|
||||
// Copy the Y plane
|
||||
src = Yplane;
|
||||
dst = swdata->pixels + rect->y * swdata->w + rect->x;
|
||||
dst = swdata->pixels + rect->y * swdata->pitches[0] + rect->x * bpp;
|
||||
length = rect->w;
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += Ypitch;
|
||||
dst += swdata->w;
|
||||
dst += swdata->pitches[0];
|
||||
}
|
||||
|
||||
// Copy the U plane
|
||||
src = Uplane;
|
||||
if (swdata->format == SDL_PIXELFORMAT_IYUV) {
|
||||
dst = swdata->pixels + swdata->h * swdata->w;
|
||||
if (swdata->format == SDL_PIXELFORMAT_P408 ||
|
||||
swdata->format == SDL_PIXELFORMAT_P416) {
|
||||
dst = swdata->pixels + swdata->h * swdata->pitches[0];
|
||||
dst += rect->y * swdata->pitches[1] + rect->x * bpp;
|
||||
length = rect->w * bpp;
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += Upitch;
|
||||
dst += swdata->pitches[1];
|
||||
}
|
||||
} else {
|
||||
dst = swdata->pixels + swdata->h * swdata->w +
|
||||
((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
|
||||
}
|
||||
dst += rect->y / 2 * ((swdata->w + 1) / 2) + rect->x / 2;
|
||||
length = (rect->w + 1) / 2;
|
||||
for (row = 0; row < (rect->h + 1) / 2; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += Upitch;
|
||||
dst += (swdata->w + 1) / 2;
|
||||
if (swdata->format == SDL_PIXELFORMAT_IYUV) {
|
||||
dst = swdata->pixels + swdata->h * swdata->w;
|
||||
} else {
|
||||
dst = swdata->pixels + swdata->h * swdata->w +
|
||||
((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
|
||||
}
|
||||
dst += rect->y / 2 * ((swdata->w + 1) / 2) + rect->x / 2;
|
||||
length = (rect->w + 1) / 2;
|
||||
for (row = 0; row < (rect->h + 1) / 2; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += Upitch;
|
||||
dst += (swdata->w + 1) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the V plane
|
||||
src = Vplane;
|
||||
if (swdata->format == SDL_PIXELFORMAT_YV12) {
|
||||
dst = swdata->pixels + swdata->h * swdata->w;
|
||||
if (swdata->format == SDL_PIXELFORMAT_P408 ||
|
||||
swdata->format == SDL_PIXELFORMAT_P416) {
|
||||
dst = swdata->pixels + swdata->h * swdata->pitches[0] + swdata->h * swdata->pitches[1];
|
||||
dst += rect->y * swdata->pitches[2] + rect->x * bpp;
|
||||
length = rect->w * bpp;
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += Vpitch;
|
||||
dst += swdata->pitches[2];
|
||||
}
|
||||
} else {
|
||||
dst = swdata->pixels + swdata->h * swdata->w +
|
||||
((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
|
||||
}
|
||||
dst += rect->y / 2 * ((swdata->w + 1) / 2) + rect->x / 2;
|
||||
length = (rect->w + 1) / 2;
|
||||
for (row = 0; row < (rect->h + 1) / 2; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += Vpitch;
|
||||
dst += (swdata->w + 1) / 2;
|
||||
if (swdata->format == SDL_PIXELFORMAT_YV12) {
|
||||
dst = swdata->pixels + swdata->h * swdata->w;
|
||||
} else {
|
||||
dst = swdata->pixels + swdata->h * swdata->w +
|
||||
((swdata->h + 1) / 2) * ((swdata->w + 1) / 2);
|
||||
}
|
||||
dst += rect->y / 2 * ((swdata->w + 1) / 2) + rect->x / 2;
|
||||
length = (rect->w + 1) / 2;
|
||||
for (row = 0; row < (rect->h + 1) / 2; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += Vpitch;
|
||||
dst += (swdata->w + 1) / 2;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -314,10 +390,12 @@ bool SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect,
|
||||
switch (swdata->format) {
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
if (rect && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w || rect->h != swdata->h)) {
|
||||
return SDL_SetError("YV12, IYUV, NV12, NV21 textures only support full surface locks");
|
||||
return SDL_SetError("YV12, IYUV, P408, P416, NV12, NV21 textures only support full surface locks");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -325,7 +403,7 @@ bool SDL_SW_LockYUVTexture(SDL_SW_YUVTexture *swdata, const SDL_Rect *rect,
|
||||
}
|
||||
|
||||
if (rect) {
|
||||
*pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
|
||||
*pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * SDL_BYTESPERPIXEL(swdata->format);
|
||||
} else {
|
||||
*pixels = swdata->planes[0];
|
||||
}
|
||||
|
||||
@@ -223,6 +223,7 @@ static D3DFORMAT PixelFormatToD3DFMT(Uint32 format)
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
return D3DFMT_L8;
|
||||
default:
|
||||
for (int i = 0; i < SDL_arraysize(d3d_format_map); i++) {
|
||||
@@ -628,17 +629,30 @@ static bool D3D_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (texturedata->yuv) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->utexture, rect->x, rect->y, rect->w, rect->h, pixels, pitch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
}
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->vtexture, rect->x, rect->y, rect->w, rect->h, pixels, pitch)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->vtexture : &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, rect->x / 2, (rect->y + 1) / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (!D3D_UpdateTextureRep(data->device, texture->format == SDL_PIXELFORMAT_YV12 ? &texturedata->utexture : &texturedata->vtexture, rect->x / 2, (rect->y + 1) / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, pixels, (pitch + 1) / 2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -688,6 +702,23 @@ static bool D3D_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
||||
return false;
|
||||
}
|
||||
|
||||
texturedata->shader_params_length = 4; // The YUV shader takes 4 float4 parameters
|
||||
texturedata->shader_params = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8);
|
||||
if (texturedata->shader_params == NULL) {
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
texturedata->yuv = true;
|
||||
|
||||
if (!D3D_CreateTextureRep(data->device, &texturedata->utexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), texture->w, texture->h)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!D3D_CreateTextureRep(data->device, &texturedata->vtexture, usage, texture->format, PixelFormatToD3DFMT(texture->format), texture->w, texture->h)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
texturedata->shader_params_length = 4; // The YUV shader takes 4 float4 parameters
|
||||
texturedata->shader_params = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8);
|
||||
if (texturedata->shader_params == NULL) {
|
||||
@@ -741,11 +772,20 @@ static bool D3D_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->texture, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->vtexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch)) {
|
||||
return false;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->utexture, rect->x, rect->y, rect->w, rect->h, Uplane, Upitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->vtexture, rect->x, rect->y, rect->w, rect->h, Vplane, Vpitch)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->utexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D_UpdateTextureRep(data->device, &texturedata->vtexture, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2005,6 +2045,7 @@ static bool D3D_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
||||
if (caps.MaxSimultaneousTextures >= 3 && data->shaders[SHADER_YUV]) {
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -266,12 +266,15 @@ static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 format, Uint32 outpu
|
||||
case SDL_PIXELFORMAT_INDEX8:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
return DXGI_FORMAT_NV12;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
return DXGI_FORMAT_P010;
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
default:
|
||||
for (int i = 0; i < SDL_arraysize(dxgi_format_map); i++) {
|
||||
if (dxgi_format_map[i].sdl == format) {
|
||||
@@ -289,8 +292,6 @@ static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(Uint32 format, Uint32 outpu
|
||||
static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(Uint32 format, Uint32 colorspace)
|
||||
{
|
||||
switch (format) {
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_NV12: // For the Y texture
|
||||
case SDL_PIXELFORMAT_NV21: // For the Y texture
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
@@ -1309,6 +1310,45 @@ static bool D3D11_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 ||
|
||||
texture->format == SDL_PIXELFORMAT_P416) {
|
||||
|
||||
textureData->yuv = true;
|
||||
|
||||
if (!GetTextureProperty(create_props, SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER, &textureData->mainTextureU)) {
|
||||
return false;
|
||||
}
|
||||
if (!textureData->mainTextureU) {
|
||||
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
|
||||
&textureDesc,
|
||||
NULL,
|
||||
&textureData->mainTextureU);
|
||||
if (FAILED(result)) {
|
||||
return WIN_SetErrorFromHRESULT("ID3D11Device1::CreateTexture2D", result);
|
||||
}
|
||||
}
|
||||
SDL_SetPointerProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_U_POINTER, textureData->mainTextureU);
|
||||
|
||||
if (!GetTextureProperty(create_props, SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER, &textureData->mainTextureV)) {
|
||||
return false;
|
||||
}
|
||||
if (!textureData->mainTextureV) {
|
||||
result = ID3D11Device_CreateTexture2D(rendererData->d3dDevice,
|
||||
&textureDesc,
|
||||
NULL,
|
||||
&textureData->mainTextureV);
|
||||
if (FAILED(result)) {
|
||||
return WIN_SetErrorFromHRESULT("ID3D11Device1::CreateTexture2D", result);
|
||||
}
|
||||
}
|
||||
SDL_SetPointerProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D11_TEXTURE_V_POINTER, textureData->mainTextureV);
|
||||
|
||||
const int bits_per_pixel = (texture->format == SDL_PIXELFORMAT_P408) ? 8 : 16;
|
||||
textureData->YCbCr_matrix = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, bits_per_pixel);
|
||||
if (!textureData->YCbCr_matrix) {
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21 ||
|
||||
texture->format == SDL_PIXELFORMAT_P010) {
|
||||
@@ -1562,16 +1602,29 @@ static bool D3D11_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
return D3D11_UpdateTextureNV(renderer, texture, rect, plane0, Ypitch, plane1, UVpitch);
|
||||
|
||||
} else if (textureData->yuv) {
|
||||
int Ypitch = srcPitch;
|
||||
int UVpitch = ((Ypitch + 1) / 2);
|
||||
const Uint8 *plane0 = (const Uint8 *)srcPixels;
|
||||
const Uint8 *plane1 = plane0 + rect->h * Ypitch;
|
||||
const Uint8 *plane2 = plane1 + ((rect->h + 1) / 2) * UVpitch;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
const Uint8 *plane0 = (const Uint8 *)srcPixels;
|
||||
const Uint8 *plane1 = plane0 + rect->h * srcPitch;
|
||||
const Uint8 *plane2 = plane1 + rect->h * srcPitch;
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
return D3D11_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane2, UVpitch, plane1, UVpitch);
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, plane1, srcPitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, plane2, srcPitch)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return D3D11_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane1, UVpitch, plane2, UVpitch);
|
||||
int Ypitch = srcPitch;
|
||||
int UVpitch = ((Ypitch + 1) / 2);
|
||||
const Uint8 *plane0 = (const Uint8 *)srcPixels;
|
||||
const Uint8 *plane1 = plane0 + rect->h * Ypitch;
|
||||
const Uint8 *plane2 = plane1 + ((rect->h + 1) / 2) * UVpitch;
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
return D3D11_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane2, UVpitch, plane1, UVpitch);
|
||||
} else {
|
||||
return D3D11_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane1, UVpitch, plane2, UVpitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1599,11 +1652,20 @@ static bool D3D11_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTexture, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch)) {
|
||||
return false;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Uplane, Upitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x, rect->y, rect->w, rect->h, Vplane, Vpitch)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureU, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D11_UpdateTextureInternal(rendererData, textureData->mainTextureV, SDL_BYTESPERPIXEL(texture->format), rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2153,6 +2215,7 @@ static void D3D11_SetupShaderConstants(SDL_Renderer *renderer, const SDL_RenderC
|
||||
break;
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
constants->texture_type = TEXTURETYPE_YUV;
|
||||
constants->input_type = INPUTTYPE_SRGB;
|
||||
break;
|
||||
@@ -2168,6 +2231,10 @@ static void D3D11_SetupShaderConstants(SDL_Renderer *renderer, const SDL_RenderC
|
||||
constants->texture_type = TEXTURETYPE_NV12;
|
||||
constants->input_type = INPUTTYPE_HDR10;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
constants->texture_type = TEXTURETYPE_YUV;
|
||||
constants->input_type = INPUTTYPE_HDR10;
|
||||
break;
|
||||
default:
|
||||
if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART) {
|
||||
constants->texture_type = TEXTURETYPE_RGB_PIXELART;
|
||||
@@ -2971,9 +3038,11 @@ static bool D3D11_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P416);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -328,12 +328,15 @@ static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(SDL_PixelFormat format, Uin
|
||||
case SDL_PIXELFORMAT_INDEX8:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
return DXGI_FORMAT_NV12;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
return DXGI_FORMAT_P010;
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
return DXGI_FORMAT_R16_UNORM;
|
||||
default:
|
||||
for (int i = 0; i < SDL_arraysize(dxgi_format_map); i++) {
|
||||
if (dxgi_format_map[i].sdl == format) {
|
||||
@@ -351,9 +354,6 @@ static DXGI_FORMAT SDLPixelFormatToDXGITextureFormat(SDL_PixelFormat format, Uin
|
||||
static DXGI_FORMAT SDLPixelFormatToDXGIMainResourceViewFormat(SDL_PixelFormat format, Uint32 colorspace)
|
||||
{
|
||||
switch (format) {
|
||||
case SDL_PIXELFORMAT_INDEX8:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_NV12: // For the Y texture
|
||||
case SDL_PIXELFORMAT_NV21: // For the Y texture
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
@@ -1740,6 +1740,55 @@ static bool D3D12_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
}
|
||||
}
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 ||
|
||||
texture->format == SDL_PIXELFORMAT_P416) {
|
||||
textureData->yuv = true;
|
||||
|
||||
if (!GetTextureProperty(create_props, SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER, &textureData->mainTextureU)) {
|
||||
return false;
|
||||
}
|
||||
if (!textureData->mainTextureU) {
|
||||
result = ID3D12Device1_CreateCommittedResource(rendererData->d3dDevice,
|
||||
&heapProps,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&textureDesc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
D3D_GUID(SDL_IID_ID3D12Resource),
|
||||
(void **)&textureData->mainTextureU);
|
||||
if (FAILED(result)) {
|
||||
return WIN_SetErrorFromHRESULT("ID3D12Device::CreateCommittedResource [texture]", result);
|
||||
}
|
||||
}
|
||||
textureData->mainResourceStateU = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
SDL_SetPointerProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D12_TEXTURE_U_POINTER, textureData->mainTextureU);
|
||||
|
||||
if (!GetTextureProperty(create_props, SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER, &textureData->mainTextureV)) {
|
||||
return false;
|
||||
}
|
||||
if (!textureData->mainTextureV) {
|
||||
result = ID3D12Device1_CreateCommittedResource(rendererData->d3dDevice,
|
||||
&heapProps,
|
||||
D3D12_HEAP_FLAG_NONE,
|
||||
&textureDesc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
NULL,
|
||||
D3D_GUID(SDL_IID_ID3D12Resource),
|
||||
(void **)&textureData->mainTextureV);
|
||||
if (FAILED(result)) {
|
||||
return WIN_SetErrorFromHRESULT("ID3D12Device::CreateCommittedResource [texture]", result);
|
||||
}
|
||||
}
|
||||
textureData->mainResourceStateV = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
SDL_SetPointerProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_D3D12_TEXTURE_V_POINTER, textureData->mainTextureV);
|
||||
|
||||
const int bits_per_pixel = (texture->format == SDL_PIXELFORMAT_P408) ? 8 : 16;
|
||||
textureData->YCbCr_matrix = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, bits_per_pixel);
|
||||
if (!textureData->YCbCr_matrix) {
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
}
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21 ||
|
||||
texture->format == SDL_PIXELFORMAT_P010) {
|
||||
@@ -2021,17 +2070,30 @@ static bool D3D12_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
}
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (textureData->yuv) {
|
||||
// Skip to the correct offset into the next texture
|
||||
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
// Skip to the correct offset into the next texture
|
||||
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, 0, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceStateU)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU)) {
|
||||
return false;
|
||||
}
|
||||
// Skip to the correct offset into the next texture
|
||||
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x, rect->y, rect->w, rect->h, srcPixels, srcPitch, &textureData->mainResourceStateV)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Skip to the correct offset into the next texture
|
||||
srcPixels = (const void *)((const Uint8 *)srcPixels + rect->h * srcPitch);
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureV : textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateV : &textureData->mainResourceStateU)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2));
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV)) {
|
||||
return false;
|
||||
// Skip to the correct offset into the next texture
|
||||
srcPixels = (const void *)((const Uint8 *)srcPixels + ((rect->h + 1) / 2) * ((srcPitch + 1) / 2));
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, texture->format == SDL_PIXELFORMAT_YV12 ? textureData->mainTextureU : textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, srcPixels, (srcPitch + 1) / 2, texture->format == SDL_PIXELFORMAT_YV12 ? &textureData->mainResourceStateU : &textureData->mainResourceStateV)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2073,11 +2135,20 @@ static bool D3D12_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTexture, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainResourceState)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch, &textureData->mainResourceStateU)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch, &textureData->mainResourceStateV)) {
|
||||
return false;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, 0, rect->x, rect->y, rect->w, rect->h, Uplane, Upitch, &textureData->mainResourceStateU)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x, rect->y, rect->w, rect->h, Vplane, Vpitch, &textureData->mainResourceStateV)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureU, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch, &textureData->mainResourceStateU)) {
|
||||
return false;
|
||||
}
|
||||
if (!D3D12_UpdateTextureInternal(rendererData, textureData->mainTextureV, 0, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch, &textureData->mainResourceStateV)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (textureData->mainTextureResourceView.ptr == rendererData->currentShaderResource.ptr) {
|
||||
// We'll need to rebind this resource after updating it
|
||||
@@ -2604,6 +2675,7 @@ static void D3D12_SetupShaderConstants(SDL_Renderer *renderer, const SDL_RenderC
|
||||
break;
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
constants->texture_type = TEXTURETYPE_YUV;
|
||||
constants->input_type = INPUTTYPE_SRGB;
|
||||
break;
|
||||
@@ -2619,6 +2691,10 @@ static void D3D12_SetupShaderConstants(SDL_Renderer *renderer, const SDL_RenderC
|
||||
constants->texture_type = TEXTURETYPE_NV12;
|
||||
constants->input_type = INPUTTYPE_HDR10;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
constants->texture_type = TEXTURETYPE_YUV;
|
||||
constants->input_type = INPUTTYPE_HDR10;
|
||||
break;
|
||||
default:
|
||||
if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_PIXELART) {
|
||||
constants->texture_type = TEXTURETYPE_RGB_PIXELART;
|
||||
@@ -3566,9 +3642,11 @@ bool D3D12_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Proper
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P416);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -287,11 +287,13 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
||||
case SDL_PIXELFORMAT_INDEX8:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
format = SDL_GPU_TEXTUREFORMAT_R8_UNORM;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
format = SDL_GPU_TEXTUREFORMAT_R16_UNORM;
|
||||
break;
|
||||
default:
|
||||
@@ -325,6 +327,11 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
||||
// Need to add size for the U and V planes
|
||||
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 ||
|
||||
texture->format == SDL_PIXELFORMAT_P416) {
|
||||
// Need to add size for the U and V planes
|
||||
size += 2 * texture->h * data->pitch;
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21 ||
|
||||
texture->format == SDL_PIXELFORMAT_P010) {
|
||||
@@ -403,6 +410,38 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 ||
|
||||
texture->format == SDL_PIXELFORMAT_P416) {
|
||||
data->yuv = true;
|
||||
|
||||
data->textureU = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_U_POINTER, NULL);
|
||||
if (data->textureU) {
|
||||
data->external_texture_u = true;
|
||||
} else {
|
||||
data->textureU = SDL_CreateGPUTexture(renderdata->device, &tci);
|
||||
if (!data->textureU) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_U_POINTER, data->textureU);
|
||||
|
||||
data->textureV = SDL_GetPointerProperty(create_props, SDL_PROP_TEXTURE_CREATE_GPU_TEXTURE_V_POINTER, NULL);
|
||||
if (data->textureV) {
|
||||
data->external_texture_v = true;
|
||||
} else {
|
||||
data->textureV = SDL_CreateGPUTexture(renderdata->device, &tci);
|
||||
if (!data->textureV) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_GPU_TEXTURE_V_POINTER, data->textureU);
|
||||
|
||||
const int bits_per_pixel = (texture->format == SDL_PIXELFORMAT_P408) ? 8 : 16;
|
||||
data->YCbCr_matrix = SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, bits_per_pixel);
|
||||
if (!data->YCbCr_matrix) {
|
||||
return SDL_SetError("Unsupported YUV colorspace");
|
||||
}
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21 ||
|
||||
texture->format == SDL_PIXELFORMAT_P010) {
|
||||
@@ -541,18 +580,27 @@ static bool GPU_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, cons
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureNV, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, UVplane, UVpitch);
|
||||
|
||||
} else if (data->yuv) {
|
||||
int Ypitch = pitch;
|
||||
int UVpitch = ((Ypitch + 1) / 2);
|
||||
const Uint8 *Yplane = (const Uint8 *)pixels;
|
||||
const Uint8 *Uplane = Yplane + rect->h * Ypitch;
|
||||
const Uint8 *Vplane = Uplane + ((rect->h + 1) / 2) * UVpitch;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
const Uint8 *Yplane = (const Uint8 *)pixels;
|
||||
const Uint8 *Uplane = Yplane + rect->h * pitch;
|
||||
const Uint8 *Vplane = Uplane + rect->h * pitch;
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, UVpitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, UVpitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x, rect->y, rect->w, rect->h, Uplane, pitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x, rect->y, rect->w, rect->h, Vplane, pitch);
|
||||
} else {
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, UVpitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, UVpitch);
|
||||
int Ypitch = pitch;
|
||||
int UVpitch = ((Ypitch + 1) / 2);
|
||||
const Uint8 *Yplane = (const Uint8 *)pixels;
|
||||
const Uint8 *Uplane = Yplane + rect->h * Ypitch;
|
||||
const Uint8 *Vplane = Uplane + ((rect->h + 1) / 2) * UVpitch;
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, UVpitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, UVpitch);
|
||||
} else {
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, UVpitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, UVpitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -576,8 +624,13 @@ static bool GPU_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
SDL_GPUCommandBuffer *cbuf = renderdata->state.command_buffer;
|
||||
SDL_GPUCopyPass *cpass = SDL_BeginGPUCopyPass(cbuf);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->texture, bpp, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch);
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x, rect->y, rect->w, rect->h, Uplane, Upitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x, rect->y, rect->w, rect->h, Vplane, Vpitch);
|
||||
} else {
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureU, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Uplane, Upitch);
|
||||
retval &= GPU_UpdateTextureInternal(renderdata, cpass, data->textureV, bpp, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch);
|
||||
}
|
||||
SDL_EndGPUCopyPass(cpass);
|
||||
return retval;
|
||||
}
|
||||
@@ -874,6 +927,7 @@ static void CalculateAdvancedShaderConstants(SDL_Renderer *renderer, const SDL_R
|
||||
break;
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
constants->texture_type = TEXTURETYPE_YUV;
|
||||
constants->input_type = INPUTTYPE_SRGB;
|
||||
break;
|
||||
@@ -889,6 +943,10 @@ static void CalculateAdvancedShaderConstants(SDL_Renderer *renderer, const SDL_R
|
||||
constants->texture_type = TEXTURETYPE_NV12;
|
||||
constants->input_type = INPUTTYPE_HDR10;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
constants->texture_type = TEXTURETYPE_YUV;
|
||||
constants->input_type = INPUTTYPE_HDR10;
|
||||
break;
|
||||
default:
|
||||
switch (texture->format) {
|
||||
case SDL_PIXELFORMAT_BGRX32:
|
||||
@@ -1842,9 +1900,11 @@ static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_P
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P416);
|
||||
|
||||
SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 16384);
|
||||
|
||||
|
||||
@@ -752,12 +752,14 @@ static bool METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
break;
|
||||
case SDL_PIXELFORMAT_INDEX8:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
pixfmt = MTLPixelFormatR8Unorm;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
pixfmt = MTLPixelFormatR16Unorm;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_RGBA64_FLOAT:
|
||||
@@ -796,13 +798,18 @@ static bool METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
|
||||
mtltextureUv = nil;
|
||||
#ifdef SDL_HAVE_YUV
|
||||
BOOL yuv = (texture->format == SDL_PIXELFORMAT_IYUV || texture->format == SDL_PIXELFORMAT_YV12);
|
||||
BOOL yuv = (texture->format == SDL_PIXELFORMAT_IYUV || texture->format == SDL_PIXELFORMAT_YV12 || texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416);
|
||||
BOOL nv12 = (texture->format == SDL_PIXELFORMAT_NV12 || texture->format == SDL_PIXELFORMAT_NV21 || texture->format == SDL_PIXELFORMAT_P010);
|
||||
|
||||
if (yuv) {
|
||||
mtltexdesc.pixelFormat = MTLPixelFormatR8Unorm;
|
||||
mtltexdesc.width = (texture->w + 1) / 2;
|
||||
mtltexdesc.height = (texture->h + 1) / 2;
|
||||
mtltexdesc.pixelFormat = pixfmt;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
mtltexdesc.width = texture->w;
|
||||
mtltexdesc.height = texture->h;
|
||||
} else {
|
||||
mtltexdesc.width = (texture->w + 1) / 2;
|
||||
mtltexdesc.height = (texture->h + 1) / 2;
|
||||
}
|
||||
mtltexdesc.textureType = MTLTextureType2DArray;
|
||||
mtltexdesc.arrayLength = 2;
|
||||
} else if (texture->format == SDL_PIXELFORMAT_P010) {
|
||||
@@ -954,8 +961,18 @@ static bool METAL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
if (texturedata.yuv) {
|
||||
int Uslice = texture->format == SDL_PIXELFORMAT_YV12 ? 1 : 0;
|
||||
int Vslice = texture->format == SDL_PIXELFORMAT_YV12 ? 0 : 1;
|
||||
int UVpitch = (pitch + 1) / 2;
|
||||
SDL_Rect UVrect = { rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2 };
|
||||
int UVpitch;
|
||||
SDL_Rect UVrect;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
UVpitch = pitch;
|
||||
UVrect = *rect;
|
||||
} else {
|
||||
UVpitch = (pitch + 1) / 2;
|
||||
UVrect.x = rect->x / 2;
|
||||
UVrect.y = rect->y / 2;
|
||||
UVrect.w = (rect->w + 1) / 2;
|
||||
UVrect.h = (rect->h + 1) / 2;
|
||||
}
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
@@ -998,7 +1015,15 @@ static bool METAL_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
SDL3METAL_TextureData *texturedata = (__bridge SDL3METAL_TextureData *)texture->internal;
|
||||
const int Uslice = 0;
|
||||
const int Vslice = 1;
|
||||
SDL_Rect UVrect = { rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2 };
|
||||
SDL_Rect UVrect;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
UVrect = *rect;
|
||||
} else {
|
||||
UVrect.x = rect->x / 2;
|
||||
UVrect.y = rect->y / 2;
|
||||
UVrect.w = (rect->w + 1) / 2;
|
||||
UVrect.h = (rect->h + 1) / 2;
|
||||
}
|
||||
|
||||
// Bail out if we're supposed to update an empty rectangle
|
||||
if (rect->w <= 0 || rect->h <= 0) {
|
||||
@@ -1451,6 +1476,8 @@ static void SetupShaderConstants(SDL_Renderer *renderer, const SDL_RenderCommand
|
||||
break;
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
constants->texture_type = TEXTURETYPE_YUV;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
@@ -2512,9 +2539,11 @@ static bool METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P416);
|
||||
|
||||
#if defined(SDL_PLATFORM_MACOS) || TARGET_OS_MACCATALYST
|
||||
data.mtllayer.displaySyncEnabled = NO;
|
||||
|
||||
@@ -435,6 +435,7 @@ static bool convert_format(Uint32 pixel_format, GLint *internalFormat, GLenum *f
|
||||
case SDL_PIXELFORMAT_INDEX8:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
*internalFormat = GL_LUMINANCE;
|
||||
@@ -593,6 +594,10 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
|
||||
// Need to add size for the U and V planes
|
||||
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
// Need to add size for the U and V planes
|
||||
size += 2 * texture->h * data->pitch;
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||
// Need to add size for the U/V plane
|
||||
@@ -724,6 +729,35 @@ static bool GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_P
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
|
||||
}
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
data->yuv = true;
|
||||
|
||||
data->utexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER, 0);
|
||||
if (data->utexture) {
|
||||
data->utexture_external = true;
|
||||
} else {
|
||||
renderdata->glGenTextures(1, &data->utexture);
|
||||
}
|
||||
data->vtexture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER, 0);
|
||||
if (data->vtexture) {
|
||||
data->vtexture_external = true;
|
||||
} else {
|
||||
renderdata->glGenTextures(1, &data->vtexture);
|
||||
}
|
||||
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
renderdata->glTexImage2D(textype, 0, internalFormat, texture_w, texture_h, 0, format, type, NULL);
|
||||
SetTextureScaleMode(renderdata, textype, texture->format, data->texture_scale_mode);
|
||||
SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture);
|
||||
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
renderdata->glTexImage2D(textype, 0, internalFormat, texture_w, texture_h, 0, format, type, NULL);
|
||||
SetTextureScaleMode(renderdata, textype, texture->format, data->texture_scale_mode);
|
||||
SetTextureAddressMode(renderdata, textype, data->texture_address_mode_u, data->texture_address_mode_v);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture);
|
||||
}
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||
data->nv12 = true;
|
||||
@@ -807,29 +841,43 @@ static bool GL_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
pixels);
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (data->yuv) {
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
} else {
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
}
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, pixels);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w, rect->h,
|
||||
data->format, data->formattype, pixels);
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
} else {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w, rect->h,
|
||||
data->format, data->formattype, pixels);
|
||||
} else {
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, ((pitch + 1) / 2));
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
} else {
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
}
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, pixels);
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
} else {
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
}
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, pixels);
|
||||
}
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, pixels);
|
||||
}
|
||||
|
||||
if (data->nv12) {
|
||||
@@ -868,17 +916,29 @@ static bool GL_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
rect->h, data->format, data->formattype,
|
||||
Yplane);
|
||||
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, Uplane);
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w, rect->h,
|
||||
data->format, data->formattype, Uplane);
|
||||
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, Vplane);
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x, rect->y, rect->w, rect->h,
|
||||
data->format, data->formattype, Vplane);
|
||||
} else {
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Upitch);
|
||||
renderdata->glBindTexture(textype, data->utexture);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, Uplane);
|
||||
|
||||
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, Vpitch);
|
||||
renderdata->glBindTexture(textype, data->vtexture);
|
||||
renderdata->glTexSubImage2D(textype, 0, rect->x / 2, rect->y / 2,
|
||||
(rect->w + 1) / 2, (rect->h + 1) / 2,
|
||||
data->format, data->formattype, Vplane);
|
||||
}
|
||||
|
||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||
}
|
||||
@@ -1977,6 +2037,7 @@ static bool GL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_Pr
|
||||
data->num_texture_units >= 3) {
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
} else {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL YUV not supported");
|
||||
}
|
||||
|
||||
@@ -1245,6 +1245,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
|
||||
#ifdef SDL_HAVE_YUV
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
@@ -1283,6 +1284,7 @@ static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, v
|
||||
#ifdef SDL_HAVE_YUV
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
@@ -1745,6 +1747,7 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
#ifdef SDL_HAVE_YUV
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
#endif
|
||||
@@ -1783,7 +1786,7 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
data->pixel_format = format;
|
||||
data->pixel_type = type;
|
||||
#ifdef SDL_HAVE_YUV
|
||||
data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
|
||||
data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12) || (texture->format == SDL_PIXELFORMAT_P408));
|
||||
data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
|
||||
#endif
|
||||
data->texture_scale_mode = texture->scaleMode;
|
||||
@@ -1798,7 +1801,11 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (data->yuv) {
|
||||
// Need to add size for the U and V planes
|
||||
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
size += 2 * texture->h * data->pitch;
|
||||
} else {
|
||||
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
|
||||
}
|
||||
} else if (data->nv12) {
|
||||
// Need to add size for the U/V plane
|
||||
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
|
||||
@@ -1821,6 +1828,15 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (data->yuv) {
|
||||
int yuv_texture_w, yuv_texture_h;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
yuv_texture_w = texture->w;
|
||||
yuv_texture_h = texture->h;
|
||||
} else {
|
||||
yuv_texture_w = (texture->w + 1) / 2;
|
||||
yuv_texture_h = (texture->h + 1) / 2;
|
||||
}
|
||||
|
||||
data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER, 0);
|
||||
if (data->texture_v) {
|
||||
data->texture_v_external = true;
|
||||
@@ -1834,7 +1850,7 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
}
|
||||
renderdata->glActiveTexture(GL_TEXTURE2);
|
||||
renderdata->glBindTexture(data->texture_type, data->texture_v);
|
||||
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
||||
renderdata->glTexImage2D(data->texture_type, 0, format, yuv_texture_w, yuv_texture_h, 0, format, type, NULL);
|
||||
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
||||
SDL_free(data->pixel_data);
|
||||
SDL_free(data);
|
||||
@@ -1857,7 +1873,7 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
|
||||
}
|
||||
renderdata->glActiveTexture(GL_TEXTURE1);
|
||||
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
||||
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
|
||||
renderdata->glTexImage2D(data->texture_type, 0, format, yuv_texture_w, yuv_texture_h, 0, format, type, NULL);
|
||||
if (!GL_CheckError("glTexImage2D()", renderer)) {
|
||||
SDL_free(data->pixel_data);
|
||||
SDL_free(data);
|
||||
@@ -2015,37 +2031,59 @@ static bool GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, co
|
||||
|
||||
#ifdef SDL_HAVE_YUV
|
||||
if (tdata->yuv) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
} else {
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
}
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
pixels, (pitch + 1) / 2, 1);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x, rect->y,
|
||||
rect->w, rect->h,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
pixels, pitch, 1);
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
} else {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x, rect->y,
|
||||
rect->w, rect->h,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
pixels, pitch, 1);
|
||||
} else {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
} else {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
}
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
pixels, (pitch + 1) / 2, 1);
|
||||
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
} else {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
}
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
pixels, (pitch + 1) / 2, 1);
|
||||
}
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
pixels, (pitch + 1) / 2, 1);
|
||||
} else if (tdata->nv12) {
|
||||
// Skip to the correct offset into the next texture
|
||||
pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
|
||||
@@ -2083,25 +2121,43 @@ static bool GLES2_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
|
||||
data->drawstate.texture = NULL; // we trash this state.
|
||||
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Vplane, Vpitch, 1);
|
||||
if (texture->format == SDL_PIXELFORMAT_P408) {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x, rect->y,
|
||||
rect->w, rect->h,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Vplane, Vpitch, 1);
|
||||
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Uplane, Upitch, 1);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x, rect->y,
|
||||
rect->w, rect->h,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Uplane, Upitch, 1);
|
||||
} else {
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Vplane, Vpitch, 1);
|
||||
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
rect->x / 2,
|
||||
rect->y / 2,
|
||||
(rect->w + 1) / 2,
|
||||
(rect->h + 1) / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Uplane, Upitch, 1);
|
||||
}
|
||||
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||
@@ -2412,6 +2468,7 @@ static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL
|
||||
#ifdef SDL_HAVE_YUV
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
||||
#endif
|
||||
|
||||
@@ -432,6 +432,8 @@ static int VULKAN_VkFormatGetNumPlanes(VkFormat vkFormat)
|
||||
{
|
||||
switch (vkFormat) {
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
|
||||
case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
|
||||
return 3;
|
||||
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
|
||||
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
|
||||
@@ -451,7 +453,10 @@ static VkDeviceSize VULKAN_GetBytesPerPixel(VkFormat vkFormat, int plane)
|
||||
case VK_FORMAT_R16G16_UNORM:
|
||||
return 4;
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM:
|
||||
case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM:
|
||||
return 1;
|
||||
case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM:
|
||||
return 2;
|
||||
case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM:
|
||||
return (plane == 0) ? 1 : 2;
|
||||
case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16:
|
||||
@@ -473,11 +478,15 @@ static VkFormat SDLPixelFormatToVkTextureFormat(SDL_PixelFormat format, Uint32 o
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
return VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM;
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
return VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16;
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
return VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM;
|
||||
default:
|
||||
for (int i = 0; i < SDL_arraysize(vk_format_map); i++) {
|
||||
if (vk_format_map[i].sdl == format) {
|
||||
@@ -2640,9 +2649,11 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
|
||||
// YUV textures must have even width and height. Also create Ycbcr conversion
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_IYUV ||
|
||||
texture->format == SDL_PIXELFORMAT_P408 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||
texture->format == SDL_PIXELFORMAT_NV21 ||
|
||||
texture->format == SDL_PIXELFORMAT_P010) {
|
||||
texture->format == SDL_PIXELFORMAT_P010 ||
|
||||
texture->format == SDL_PIXELFORMAT_P416) {
|
||||
const uint32_t YUV_SD_THRESHOLD = 576;
|
||||
|
||||
// Check that we have VK_KHR_sampler_ycbcr_conversion support
|
||||
@@ -2653,9 +2664,12 @@ static bool VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, S
|
||||
VkSamplerYcbcrConversionCreateInfoKHR samplerYcbcrConversionCreateInfo = { 0 };
|
||||
samplerYcbcrConversionCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR;
|
||||
|
||||
// Pad width/height to multiple of 2
|
||||
width = (width + 1) & ~1;
|
||||
height = (height + 1) & ~1;
|
||||
if (texture->format != SDL_PIXELFORMAT_P408 &&
|
||||
texture->format != SDL_PIXELFORMAT_P416) {
|
||||
// Pad width/height to multiple of 2
|
||||
width = (width + 1) & ~1;
|
||||
height = (height + 1) & ~1;
|
||||
}
|
||||
|
||||
// Create samplerYcbcrConversion which will be used on the VkImageView and VkSampler
|
||||
samplerYcbcrConversionCreateInfo.format = textureFormat;
|
||||
@@ -2974,16 +2988,24 @@ static bool VULKAN_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
|
||||
|
||||
} else if (numPlanes == 3) {
|
||||
// YUV data
|
||||
int Ypitch = srcPitch;
|
||||
int UVpitch = ((Ypitch + 1) / 2);
|
||||
const Uint8 *plane0 = (const Uint8 *)srcPixels;
|
||||
const Uint8 *plane1 = plane0 + rect->h * Ypitch;
|
||||
const Uint8 *plane2 = plane1 + ((rect->h + 1) / 2) * UVpitch;
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
const Uint8 *plane0 = (const Uint8 *)srcPixels;
|
||||
const Uint8 *plane1 = plane0 + rect->h * srcPitch;
|
||||
const Uint8 *plane2 = plane1 + rect->h * srcPitch;
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
return VULKAN_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane2, UVpitch, plane1, UVpitch);
|
||||
return VULKAN_UpdateTextureYUV(renderer, texture, rect, plane0, srcPitch, plane1, srcPitch, plane2, srcPitch);
|
||||
} else {
|
||||
return VULKAN_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane1, UVpitch, plane2, UVpitch);
|
||||
int Ypitch = srcPitch;
|
||||
int UVpitch = ((Ypitch + 1) / 2);
|
||||
const Uint8 *plane0 = (const Uint8 *)srcPixels;
|
||||
const Uint8 *plane1 = plane0 + rect->h * Ypitch;
|
||||
const Uint8 *plane2 = plane1 + ((rect->h + 1) / 2) * UVpitch;
|
||||
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
return VULKAN_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane2, UVpitch, plane1, UVpitch);
|
||||
} else {
|
||||
return VULKAN_UpdateTextureYUV(renderer, texture, rect, plane0, Ypitch, plane1, UVpitch, plane2, UVpitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -3010,7 +3032,14 @@ static bool VULKAN_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture
|
||||
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 0, rect->x, rect->y, rect->w, rect->h, Yplane, Ypitch, &textureData->mainImage.imageLayout)) {
|
||||
return false;
|
||||
}
|
||||
if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
if (texture->format == SDL_PIXELFORMAT_P408 || texture->format == SDL_PIXELFORMAT_P416) {
|
||||
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x, rect->y, rect->w, rect->h, Uplane, Upitch, &textureData->mainImage.imageLayout)) {
|
||||
return false;
|
||||
}
|
||||
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 2, rect->x, rect->y, rect->w, rect->h, Vplane, Vpitch, &textureData->mainImage.imageLayout)) {
|
||||
return false;
|
||||
}
|
||||
} else if (texture->format == SDL_PIXELFORMAT_YV12) {
|
||||
if (!VULKAN_UpdateTextureInternal(rendererData, textureData->mainImage.image, textureData->mainImage.format, 1, rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2, Vplane, Vpitch, &textureData->mainImage.imageLayout)) {
|
||||
return false;
|
||||
}
|
||||
@@ -3450,11 +3479,13 @@ static void VULKAN_SetupShaderConstants(SDL_Renderer *renderer, const SDL_Render
|
||||
switch (texture->format) {
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_P408:
|
||||
case SDL_PIXELFORMAT_NV12:
|
||||
case SDL_PIXELFORMAT_NV21:
|
||||
constants->input_type = INPUTTYPE_SRGB;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_P010:
|
||||
case SDL_PIXELFORMAT_P416:
|
||||
constants->input_type = INPUTTYPE_HDR10;
|
||||
break;
|
||||
default:
|
||||
@@ -4623,9 +4654,11 @@ static bool VULKAN_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SD
|
||||
if (rendererData->supportsKHRSamplerYCbCrConversion) {
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P408);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P010);
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_P416);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user