summaryrefslogtreecommitdiff
path: root/source/3rd-party/SDL2/src/render/SDL_yuv_sw.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/3rd-party/SDL2/src/render/SDL_yuv_sw.c')
-rw-r--r--source/3rd-party/SDL2/src/render/SDL_yuv_sw.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/render/SDL_yuv_sw.c b/source/3rd-party/SDL2/src/render/SDL_yuv_sw.c
new file mode 100644
index 0000000..c227cdc
--- /dev/null
+++ b/source/3rd-party/SDL2/src/render/SDL_yuv_sw.c
@@ -0,0 +1,414 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../SDL_internal.h"
+
+/* This is the software implementation of the YUV texture support */
+
+#include "SDL_assert.h"
+
+#include "SDL_yuv_sw_c.h"
+
+
+SDL_SW_YUVTexture *
+SDL_SW_CreateYUVTexture(Uint32 format, int w, int h)
+{
+ SDL_SW_YUVTexture *swdata;
+
+ switch (format) {
+ case SDL_PIXELFORMAT_YV12:
+ case SDL_PIXELFORMAT_IYUV:
+ case SDL_PIXELFORMAT_YUY2:
+ case SDL_PIXELFORMAT_UYVY:
+ case SDL_PIXELFORMAT_YVYU:
+ case SDL_PIXELFORMAT_NV12:
+ case SDL_PIXELFORMAT_NV21:
+ break;
+ default:
+ SDL_SetError("Unsupported YUV format");
+ return NULL;
+ }
+
+ swdata = (SDL_SW_YUVTexture *) SDL_calloc(1, sizeof(*swdata));
+ if (!swdata) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ swdata->format = format;
+ swdata->target_format = SDL_PIXELFORMAT_UNKNOWN;
+ swdata->w = w;
+ swdata->h = h;
+ {
+ const int sz_plane = w * h;
+ const int sz_plane_chroma = ((w + 1) / 2) * ((h + 1) / 2);
+ const int sz_plane_packed = ((w + 1) / 2) * h;
+ int dst_size = 0;
+ switch(format)
+ {
+ case SDL_PIXELFORMAT_YV12: /**< Planar mode: Y + V + U (3 planes) */
+ case SDL_PIXELFORMAT_IYUV: /**< Planar mode: Y + U + V (3 planes) */
+ dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
+ break;
+
+ case SDL_PIXELFORMAT_YUY2: /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
+ case SDL_PIXELFORMAT_UYVY: /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
+ case SDL_PIXELFORMAT_YVYU: /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
+ dst_size = 4 * sz_plane_packed;
+ break;
+
+ case SDL_PIXELFORMAT_NV12: /**< Planar mode: Y + U/V interleaved (2 planes) */
+ case SDL_PIXELFORMAT_NV21: /**< Planar mode: Y + V/U interleaved (2 planes) */
+ dst_size = sz_plane + sz_plane_chroma + sz_plane_chroma;
+ break;
+
+ default:
+ SDL_assert(0 && "We should never get here (caught above)");
+ break;
+ }
+ swdata->pixels = (Uint8 *) SDL_malloc(dst_size);
+ if (!swdata->pixels) {
+ SDL_SW_DestroyYUVTexture(swdata);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+ }
+
+ /* Find the pitch and offset values for the texture */
+ switch (format) {
+ case SDL_PIXELFORMAT_YV12:
+ case SDL_PIXELFORMAT_IYUV:
+ swdata->pitches[0] = w;
+ swdata->pitches[1] = (swdata->pitches[0] + 1) / 2;
+ swdata->pitches[2] = (swdata->pitches[0] + 1) / 2;
+ 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 + 1) / 2);
+ 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;
+ swdata->pitches[1] = 2 * ((swdata->pitches[0] + 1) / 2);
+ swdata->planes[0] = swdata->pixels;
+ swdata->planes[1] = swdata->planes[0] + swdata->pitches[0] * h;
+ break;
+
+ default:
+ SDL_assert(0 && "We should never get here (caught above)");
+ break;
+ }
+
+ /* We're all done.. */
+ return (swdata);
+}
+
+int
+SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
+ int *pitch)
+{
+ *pixels = swdata->planes[0];
+ *pitch = swdata->pitches[0];
+ return 0;
+}
+
+int
+SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
+ const void *pixels, int pitch)
+{
+ switch (swdata->format) {
+ case SDL_PIXELFORMAT_YV12:
+ case SDL_PIXELFORMAT_IYUV:
+ if (rect->x == 0 && rect->y == 0 &&
+ rect->w == swdata->w && rect->h == swdata->h) {
+ SDL_memcpy(swdata->pixels, pixels,
+ (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
+ } else {
+ Uint8 *src, *dst;
+ int row;
+ size_t length;
+
+ /* Copy the Y plane */
+ src = (Uint8 *) pixels;
+ dst = swdata->pixels + rect->y * swdata->w + rect->x;
+ length = rect->w;
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, src, length);
+ src += pitch;
+ dst += swdata->w;
+ }
+
+ /* Copy the next plane */
+ src = (Uint8 *) pixels + rect->h * pitch;
+ dst = swdata->pixels + swdata->h * swdata->w;
+ 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 += (pitch + 1)/2;
+ dst += (swdata->w + 1)/2;
+ }
+
+ /* Copy the next plane */
+ src = (Uint8 *) pixels + rect->h * pitch + ((rect->h + 1) / 2) * ((pitch + 1) / 2);
+ 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 += (pitch + 1)/2;
+ dst += (swdata->w + 1)/2;
+ }
+ }
+ break;
+ case SDL_PIXELFORMAT_YUY2:
+ case SDL_PIXELFORMAT_UYVY:
+ case SDL_PIXELFORMAT_YVYU:
+ {
+ Uint8 *src, *dst;
+ int row;
+ size_t length;
+
+ src = (Uint8 *) pixels;
+ dst =
+ swdata->planes[0] + rect->y * swdata->pitches[0] +
+ rect->x * 2;
+ length = 4 * ((rect->w + 1) / 2);
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, src, length);
+ src += pitch;
+ dst += swdata->pitches[0];
+ }
+ }
+ break;
+ case SDL_PIXELFORMAT_NV12:
+ case SDL_PIXELFORMAT_NV21:
+ {
+ if (rect->x == 0 && rect->y == 0 && rect->w == swdata->w && rect->h == swdata->h) {
+ SDL_memcpy(swdata->pixels, pixels,
+ (swdata->h * swdata->w) + 2* ((swdata->h + 1) /2) * ((swdata->w + 1) / 2));
+ } else {
+
+ Uint8 *src, *dst;
+ int row;
+ size_t length;
+
+ /* Copy the Y plane */
+ src = (Uint8 *) pixels;
+ dst = swdata->pixels + rect->y * swdata->w + rect->x;
+ length = rect->w;
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, src, length);
+ src += pitch;
+ dst += swdata->w;
+ }
+
+ /* Copy the next plane */
+ src = (Uint8 *) pixels + rect->h * pitch;
+ dst = swdata->pixels + swdata->h * swdata->w;
+ dst += 2 * ((rect->y + 1)/2) * ((swdata->w + 1) / 2) + 2 * (rect->x/2);
+ length = 2 * ((rect->w + 1) / 2);
+ for (row = 0; row < (rect->h + 1)/2; ++row) {
+ SDL_memcpy(dst, src, length);
+ src += 2 * ((pitch + 1)/2);
+ dst += 2 * ((swdata->w + 1)/2);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+SDL_SW_UpdateYUVTexturePlanar(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
+ const Uint8 *Yplane, int Ypitch,
+ const Uint8 *Uplane, int Upitch,
+ const Uint8 *Vplane, int Vpitch)
+{
+ const Uint8 *src;
+ Uint8 *dst;
+ int row;
+ size_t length;
+
+ /* Copy the Y plane */
+ src = Yplane;
+ dst = swdata->pixels + rect->y * swdata->w + rect->x;
+ length = rect->w;
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, src, length);
+ src += Ypitch;
+ dst += swdata->w;
+ }
+
+ /* Copy the U plane */
+ src = Uplane;
+ 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;
+ } 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 0;
+}
+
+int
+SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
+ void **pixels, int *pitch)
+{
+ switch (swdata->format) {
+ case SDL_PIXELFORMAT_YV12:
+ case SDL_PIXELFORMAT_IYUV:
+ 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");
+ }
+ break;
+ }
+
+ if (rect) {
+ *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
+ } else {
+ *pixels = swdata->planes[0];
+ }
+ *pitch = swdata->pitches[0];
+ return 0;
+}
+
+void
+SDL_SW_UnlockYUVTexture(SDL_SW_YUVTexture * swdata)
+{
+}
+
+int
+SDL_SW_CopyYUVToRGB(SDL_SW_YUVTexture * swdata, const SDL_Rect * srcrect,
+ Uint32 target_format, int w, int h, void *pixels,
+ int pitch)
+{
+ int stretch;
+
+ /* Make sure we're set up to display in the desired format */
+ if (target_format != swdata->target_format && swdata->display) {
+ SDL_FreeSurface(swdata->display);
+ swdata->display = NULL;
+ }
+
+ stretch = 0;
+ if (srcrect->x || srcrect->y || srcrect->w < swdata->w || srcrect->h < swdata->h) {
+ /* The source rectangle has been clipped.
+ Using a scratch surface is easier than adding clipped
+ source support to all the blitters, plus that would
+ slow them down in the general unclipped case.
+ */
+ stretch = 1;
+ } else if ((srcrect->w != w) || (srcrect->h != h)) {
+ stretch = 1;
+ }
+ if (stretch) {
+ int bpp;
+ Uint32 Rmask, Gmask, Bmask, Amask;
+
+ if (swdata->display) {
+ swdata->display->w = w;
+ swdata->display->h = h;
+ swdata->display->pixels = pixels;
+ swdata->display->pitch = pitch;
+ } else {
+ /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
+ SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
+ &Bmask, &Amask);
+ swdata->display =
+ SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask,
+ Gmask, Bmask, Amask);
+ if (!swdata->display) {
+ return (-1);
+ }
+ }
+ if (!swdata->stretch) {
+ /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
+ SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
+ &Bmask, &Amask);
+ swdata->stretch =
+ SDL_CreateRGBSurface(0, swdata->w, swdata->h, bpp, Rmask,
+ Gmask, Bmask, Amask);
+ if (!swdata->stretch) {
+ return (-1);
+ }
+ }
+ pixels = swdata->stretch->pixels;
+ pitch = swdata->stretch->pitch;
+ }
+ if (SDL_ConvertPixels(swdata->w, swdata->h, swdata->format,
+ swdata->planes[0], swdata->pitches[0],
+ target_format, pixels, pitch) < 0) {
+ return -1;
+ }
+ if (stretch) {
+ SDL_Rect rect = *srcrect;
+ SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
+ }
+ return 0;
+}
+
+void
+SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata)
+{
+ if (swdata) {
+ SDL_free(swdata->pixels);
+ SDL_FreeSurface(swdata->stretch);
+ SDL_FreeSurface(swdata->display);
+ SDL_free(swdata);
+ }
+}
+
+/* vi: set ts=4 sw=4 expandtab: */