diff options
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.c | 414 | 
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: */ | 
