Atlas - SDL_yuv_sw.c

Home / ext / SDL2 / src / render Lines: 1 | Size: 13899 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../SDL_internal.h" 22 23/* This is the software implementation of the YUV texture support */ 24 25#include "SDL_assert.h" 26 27#include "SDL_yuv_sw_c.h" 28 29 30SDL_SW_YUVTexture * 31SDL_SW_CreateYUVTexture(Uint32 format, int w, int h) 32{ 33 SDL_SW_YUVTexture *swdata; 34 35 switch (format) { 36 case SDL_PIXELFORMAT_YV12: 37 case SDL_PIXELFORMAT_IYUV: 38 case SDL_PIXELFORMAT_YUY2: 39 case SDL_PIXELFORMAT_UYVY: 40 case SDL_PIXELFORMAT_YVYU: 41 case SDL_PIXELFORMAT_NV12: 42 case SDL_PIXELFORMAT_NV21: 43 break; 44 default: 45 SDL_SetError("Unsupported YUV format"); 46 return NULL; 47 } 48 49 swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata)); 50 if (!swdata) { 51 SDL_OutOfMemory(); 52 return NULL; 53 } 54 55 swdata->format = format; 56 swdata->target_format = SDL_PIXELFORMAT_UNKNOWN; 57 swdata->w = w; 58 swdata->h = h; 59 { 60 const int sz_plane = w * h; 61 const int sz_plane_chroma = ((w + 1) / 2) * ((h + 1) / 2); 62 const int sz_plane_packed = ((w + 1) / 2) * h; 63 int dst_size = 0; 64 switch(format) 65 { 66 case SDL_PIXELFORMAT_YV12: /**< Planar mode: Y + V + U (3 planes) */ 67 case SDL_PIXELFORMAT_IYUV: /**< Planar mode: Y + U + V (3 planes) */ 68 dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma; 69 break; 70 71 case SDL_PIXELFORMAT_YUY2: /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */ 72 case SDL_PIXELFORMAT_UYVY: /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */ 73 case SDL_PIXELFORMAT_YVYU: /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */ 74 dst_size = 4 * sz_plane_packed; 75 break; 76 77 case SDL_PIXELFORMAT_NV12: /**< Planar mode: Y + U/V interleaved (2 planes) */ 78 case SDL_PIXELFORMAT_NV21: /**< Planar mode: Y + V/U interleaved (2 planes) */ 79 dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma; 80 break; 81 82 default: 83 SDL_assert(0 && "We should never get here (caught above)"); 84 break; 85 } 86 swdata->pixels = (Uint8 *) SDL_malloc(dst_size); 87 if (!swdata->pixels) { 88 SDL_SW_DestroyYUVTexture(swdata); 89 SDL_OutOfMemory(); 90 return NULL; 91 } 92 } 93 94 /* Find the pitch and offset values for the texture */ 95 switch (format) { 96 case SDL_PIXELFORMAT_YV12: 97 case SDL_PIXELFORMAT_IYUV: 98 swdata->pitches[0] = w; 99 swdata->pitches[1] = (swdata->pitches[0] + 1) / 2; 100 swdata->pitches[2] = (swdata->pitches[0] + 1) / 2; 101 swdata->planes[0] = swdata->pixels; 102 swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h; 103 swdata->planes[2] = swdata->planes[1] + swdata->pitches[1] * ((h + 1) / 2); 104 break; 105 case SDL_PIXELFORMAT_YUY2: 106 case SDL_PIXELFORMAT_UYVY: 107 case SDL_PIXELFORMAT_YVYU: 108 swdata->pitches[0] = ((w + 1) / 2) * 4; 109 swdata->planes[0] = swdata->pixels; 110 break; 111 112 case SDL_PIXELFORMAT_NV12: 113 case SDL_PIXELFORMAT_NV21: 114 swdata->pitches[0] = w; 115 swdata->pitches[1] = 2 * ((swdata->pitches[0] + 1) / 2); 116 swdata->planes[0] = swdata->pixels; 117 swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h; 118 break; 119 120 default: 121 SDL_assert(0 && "We should never get here (caught above)"); 122 break; 123 } 124 125 /* We're all done.. */ 126 return (swdata); 127} 128 129int 130SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels, 131 int *pitch) 132{ 133 *pixels = swdata->planes[0]; 134 *pitch = swdata->pitches[0]; 135 return 0; 136} 137 138int 139SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect, 140 const void *pixels, int pitch) 141{ 142 switch (swdata->format) { 143 case SDL_PIXELFORMAT_YV12: 144 case SDL_PIXELFORMAT_IYUV: 145 if (rect->x == 0 && rect->y == 0 && 146 rect->w == swdata->w && rect->h == swdata->h) { 147 SDL_memcpy(swdata->pixels, pixels, 148 (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2)); 149 } else { 150 Uint8 *src, *dst; 151 int row; 152 size_t length; 153 154 /* Copy the Y plane */ 155 src = (Uint8 *) pixels; 156 dst = swdata->pixels + rect->y * swdata->w + rect->x; 157 length = rect->w; 158 for (row = 0; row < rect->h; ++row) { 159 SDL_memcpy(dst, src, length); 160 src += pitch; 161 dst += swdata->w; 162 } 163 164 /* Copy the next plane */ 165 src = (Uint8 *) pixels + rect->h * pitch; 166 dst = swdata->pixels + swdata->h * swdata->w; 167 dst += rect->y/2 * ((swdata->w + 1) / 2) + rect->x/2; 168 length = (rect->w + 1) / 2; 169 for (row = 0; row < (rect->h + 1)/2; ++row) { 170 SDL_memcpy(dst, src, length); 171 src += (pitch + 1)/2; 172 dst += (swdata->w + 1)/2; 173 } 174 175 /* Copy the next plane */ 176 src = (Uint8 *) pixels + rect->h * pitch + ((rect->h + 1) / 2) * ((pitch + 1) / 2); 177 dst = swdata->pixels + swdata->h * swdata->w + 178 ((swdata->h + 1)/2) * ((swdata->w+1) / 2); 179 dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2; 180 length = (rect->w + 1) / 2; 181 for (row = 0; row < (rect->h + 1)/2; ++row) { 182 SDL_memcpy(dst, src, length); 183 src += (pitch + 1)/2; 184 dst += (swdata->w + 1)/2; 185 } 186 } 187 break; 188 case SDL_PIXELFORMAT_YUY2: 189 case SDL_PIXELFORMAT_UYVY: 190 case SDL_PIXELFORMAT_YVYU: 191 { 192 Uint8 *src, *dst; 193 int row; 194 size_t length; 195 196 src = (Uint8 *) pixels; 197 dst = 198 swdata->planes[0] + rect->y * swdata->pitches[0] + 199 rect->x * 2; 200 length = 4 * ((rect->w + 1) / 2); 201 for (row = 0; row < rect->h; ++row) { 202 SDL_memcpy(dst, src, length); 203 src += pitch; 204 dst += swdata->pitches[0]; 205 } 206 } 207 break; 208 case SDL_PIXELFORMAT_NV12: 209 case SDL_PIXELFORMAT_NV21: 210 { 211 if (rect->x == 0 && rect->y == 0 && rect->w == swdata->w && rect->h == swdata->h) { 212 SDL_memcpy(swdata->pixels, pixels, 213 (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2)); 214 } else { 215 216 Uint8 *src, *dst; 217 int row; 218 size_t length; 219 220 /* Copy the Y plane */ 221 src = (Uint8 *) pixels; 222 dst = swdata->pixels + rect->y * swdata->w + rect->x; 223 length = rect->w; 224 for (row = 0; row < rect->h; ++row) { 225 SDL_memcpy(dst, src, length); 226 src += pitch; 227 dst += swdata->w; 228 } 229 230 /* Copy the next plane */ 231 src = (Uint8 *) pixels + rect->h * pitch; 232 dst = swdata->pixels + swdata->h * swdata->w; 233 dst += 2 * ((rect->y + 1)/2) * ((swdata->w + 1) / 2) + 2 * (rect->x/2); 234 length = 2 * ((rect->w + 1) / 2); 235 for (row = 0; row < (rect->h + 1)/2; ++row) { 236 SDL_memcpy(dst, src, length); 237 src += 2 * ((pitch + 1)/2); 238 dst += 2 * ((swdata->w + 1)/2); 239 } 240 } 241 } 242 } 243 return 0; 244} 245 246int 247SDL_SW_UpdateYUVTexturePlanar(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect, 248 const Uint8 *Yplane, int Ypitch, 249 const Uint8 *Uplane, int Upitch, 250 const Uint8 *Vplane, int Vpitch) 251{ 252 const Uint8 *src; 253 Uint8 *dst; 254 int row; 255 size_t length; 256 257 /* Copy the Y plane */ 258 src = Yplane; 259 dst = swdata->pixels + rect->y * swdata->w + rect->x; 260 length = rect->w; 261 for (row = 0; row < rect->h; ++row) { 262 SDL_memcpy(dst, src, length); 263 src += Ypitch; 264 dst += swdata->w; 265 } 266 267 /* Copy the U plane */ 268 src = Uplane; 269 if (swdata->format == SDL_PIXELFORMAT_IYUV) { 270 dst = swdata->pixels + swdata->h * swdata->w; 271 } else { 272 dst = swdata->pixels + swdata->h * swdata->w + 273 ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2); 274 } 275 dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2; 276 length = (rect->w + 1) / 2; 277 for (row = 0; row < (rect->h + 1)/2; ++row) { 278 SDL_memcpy(dst, src, length); 279 src += Upitch; 280 dst += (swdata->w + 1)/2; 281 } 282 283 /* Copy the V plane */ 284 src = Vplane; 285 if (swdata->format == SDL_PIXELFORMAT_YV12) { 286 dst = swdata->pixels + swdata->h * swdata->w; 287 } else { 288 dst = swdata->pixels + swdata->h * swdata->w + 289 ((swdata->h + 1) / 2) * ((swdata->w + 1) / 2); 290 } 291 dst += rect->y/2 * ((swdata->w + 1)/2) + rect->x/2; 292 length = (rect->w + 1) / 2; 293 for (row = 0; row < (rect->h + 1)/2; ++row) { 294 SDL_memcpy(dst, src, length); 295 src += Vpitch; 296 dst += (swdata->w + 1)/2; 297 } 298 return 0; 299} 300 301int 302SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect, 303 void **pixels, int *pitch) 304{ 305 switch (swdata->format) { 306 case SDL_PIXELFORMAT_YV12: 307 case SDL_PIXELFORMAT_IYUV: 308 case SDL_PIXELFORMAT_NV12: 309 case SDL_PIXELFORMAT_NV21: 310 if (rect 311 && (rect->x != 0 || rect->y != 0 || rect->w != swdata->w 312 || rect->h != swdata->h)) { 313 return SDL_SetError 314 ("YV12, IYUV, NV12, NV21 textures only support full surface locks"); 315 } 316 break; 317 } 318 319 if (rect) { 320 *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2; 321 } else { 322 *pixels = swdata->planes[0]; 323 } 324 *pitch = swdata->pitches[0]; 325 return 0; 326} 327 328void 329SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture * swdata) 330{ 331} 332 333int 334SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect, 335 Uint32 target_format, int w, int h, void *pixels, 336 int pitch) 337{ 338 int stretch; 339 340 /* Make sure we're set up to display in the desired format */ 341 if (target_format != swdata->target_format && swdata->display) { 342 SDL_FreeSurface(swdata->display); 343 swdata->display = NULL; 344 } 345 346 stretch = 0; 347 if (srcrect->x || srcrect->y || srcrect->w < swdata->w || srcrect->h < swdata->h) { 348 /* The source rectangle has been clipped. 349 Using a scratch surface is easier than adding clipped 350 source support to all the blitters, plus that would 351 slow them down in the general unclipped case. 352 */ 353 stretch = 1; 354 } else if ((srcrect->w != w) || (srcrect->h != h)) { 355 stretch = 1; 356 } 357 if (stretch) { 358 int bpp; 359 Uint32 Rmask, Gmask, Bmask, Amask; 360 361 if (swdata->display) { 362 swdata->display->w = w; 363 swdata->display->h = h; 364 swdata->display->pixels = pixels; 365 swdata->display->pitch = pitch; 366 } else { 367 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */ 368 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask, 369 &Bmask, &Amask); 370 swdata->display = 371 SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask, 372 Gmask, Bmask, Amask); 373 if (!swdata->display) { 374 return (-1); 375 } 376 } 377 if (!swdata->stretch) { 378 /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */ 379 SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask, 380 &Bmask, &Amask); 381 swdata->stretch = 382 SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask, 383 Gmask, Bmask, Amask); 384 if (!swdata->stretch) { 385 return (-1); 386 } 387 } 388 pixels = swdata->stretch->pixels; 389 pitch = swdata->stretch->pitch; 390 } 391 if (SDL_ConvertPixels(swdata->w, swdata->h, swdata->format, 392 swdata->planes[0], swdata->pitches[0], 393 target_format, pixels, pitch) < 0) { 394 return -1; 395 } 396 if (stretch) { 397 SDL_Rect rect = *srcrect; 398 SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL); 399 } 400 return 0; 401} 402 403void 404SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata) 405{ 406 if (swdata) { 407 SDL_free(swdata->pixels); 408 SDL_FreeSurface(swdata->stretch); 409 SDL_FreeSurface(swdata->display); 410 SDL_free(swdata); 411 } 412} 413 414/* vi: set ts=4 sw=4 expandtab: */ 415
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.