Software YUV texture support in progress... SDL-1.3
authorSam Lantinga <slouken@libsdl.org>
Sun, 18 Jun 2006 06:35:41 +0000
branchSDL-1.3
changeset 1684 c4aa1a2f48f1
parent 1683 396a35389351
child 1685 66267c6a0b12
Software YUV texture support in progress...
include/SDL_pixels.h
src/SDL_compat.c
src/video/SDL_renderer_sw.c
src/video/SDL_video.c
src/video/SDL_yuv_sw.c
src/video/SDL_yuv_sw_c.h
--- a/include/SDL_pixels.h	Sat Jun 17 06:45:14 2006 +0000
+++ b/include/SDL_pixels.h	Sun Jun 18 06:35:41 2006 +0000
@@ -179,11 +179,16 @@
         SDL_DEFINE_PIXELFORMAT(SDL_PixelType_Packed32, SDL_PackedOrder_ARGB,
                                SDL_PackedLayout_2101010, 32, 4),
 
-    SDL_PixelFormat_YV12 = SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
-    SDL_PixelFormat_IYUV = SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'),
-    SDL_PixelFormat_YUY2 = SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'),
-    SDL_PixelFormat_UYVY = SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
-    SDL_PixelFormat_YVYU = SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'),
+    SDL_PixelFormat_YV12 =      /* Planar mode: Y + V + U  (3 planes) */
+        SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
+    SDL_PixelFormat_IYUV =      /* Planar mode: Y + U + V  (3 planes) */
+        SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'),
+    SDL_PixelFormat_YUY2 =      /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
+        SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'),
+    SDL_PixelFormat_UYVY =      /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
+        SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
+    SDL_PixelFormat_YVYU =      /* Packed mode: Y0+V0+Y1+U0 (1 plane) */
+        SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'),
 };
 
 typedef struct SDL_Color
--- a/src/SDL_compat.c	Sat Jun 17 06:45:14 2006 +0000
+++ b/src/SDL_compat.c	Sun Jun 18 06:35:41 2006 +0000
@@ -1176,121 +1176,159 @@
         SDL_memset(SDL_cursor->save[0], 0, savelen);
     }
 }
+#endif
+
+struct private_yuvhwdata
+{
+    Uint16 pitches[3];
+    Uint8 *planes[3];
+
+    SDL_TextureID textureID;
+};
 
 SDL_Overlay *
 SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display)
 {
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    SDL_Window *window;
-    const char *yuv_hwaccel;
     SDL_Overlay *overlay;
+    Uint32 texture_format;
 
-    window = SDL_GetWindowFromSurface(display);
-    if (window && (window->flags & SDL_WINDOW_OPENGL)) {
+    if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
         SDL_SetError("YUV overlays are not supported in OpenGL mode");
         return NULL;
     }
 
-    /* Display directly on video surface, if possible */
-    if (SDL_getenv("SDL_VIDEO_YUV_DIRECT")) {
-        if (window &&
-            ((window->surface->format->BytesPerPixel == 2) ||
-             (window->surface->format->BytesPerPixel == 4))) {
-            display = window->surface;
-        }
+    if (display != SDL_PublicSurface) {
+        SDL_SetError("YUV display is only supported on the screen surface");
+        return NULL;
+    }
+
+    switch (format) {
+    case SDL_YV12_OVERLAY:
+        texture_format = SDL_PixelFormat_YV12;
+        break;
+    case SDL_IYUV_OVERLAY:
+        texture_format = SDL_PixelFormat_IYUV;
+        break;
+    case SDL_YUY2_OVERLAY:
+        texture_format = SDL_PixelFormat_YUY2;
+        break;
+    case SDL_UYVY_OVERLAY:
+        texture_format = SDL_PixelFormat_UYVY;
+        break;
+    case SDL_YVYU_OVERLAY:
+        texture_format = SDL_PixelFormat_YVYU;
+        break;
+    default:
+        SDL_SetError("Unknown YUV format");
+        return NULL;
+    }
+
+    overlay = (SDL_Overlay *) SDL_malloc(sizeof(*overlay));
+    if (!overlay) {
+        SDL_OutOfMemory();
+        return NULL;
     }
-    overlay = NULL;
-    yuv_hwaccel = SDL_getenv("SDL_VIDEO_YUV_HWACCEL");
-    if (((display->flags & SDL_SCREEN_SURFACE) && _this->CreateYUVOverlay) &&
-        (!yuv_hwaccel || (SDL_atoi(yuv_hwaccel) > 0))) {
-        overlay = _this->CreateYUVOverlay(_this, w, h, format, display);
+    SDL_zerop(overlay);
+
+    overlay->hwdata =
+        (struct private_yuvhwdata *) SDL_malloc(sizeof(*overlay->hwdata));
+    if (!overlay->hwdata) {
+        SDL_free(overlay);
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    overlay->format = format;
+    overlay->w = w;
+    overlay->h = h;
+    if (format == SDL_YV12_OVERLAY || format == SDL_IYUV_OVERLAY) {
+        overlay->planes = 3;
+    } else {
+        overlay->planes = 1;
     }
-    /* If hardware YUV overlay failed ... */
-    if (overlay == NULL) {
-        overlay = SDL_CreateYUV_SW(_this, w, h, format, display);
+    overlay->pitches = overlay->hwdata->pitches;
+    overlay->pixels = overlay->hwdata->planes;
+
+    switch (format) {
+    case SDL_YV12_OVERLAY:
+    case SDL_IYUV_OVERLAY:
+        overlay->pitches[0] = overlay->w;
+        overlay->pitches[1] = overlay->w / 2;
+        overlay->pitches[2] = overlay->w / 2;
+        break;
+    case SDL_YUY2_OVERLAY:
+    case SDL_UYVY_OVERLAY:
+    case SDL_YVYU_OVERLAY:
+        overlay->pitches[0] = overlay->h * 2;
+        break;
     }
+
+    overlay->hwdata->textureID =
+        SDL_CreateTexture(texture_format, SDL_TextureAccess_Local, w, h);
+    if (!overlay->hwdata->textureID) {
+        SDL_FreeYUVOverlay(overlay);
+        return NULL;
+    }
+
     return overlay;
 }
 
 int
 SDL_LockYUVOverlay(SDL_Overlay * overlay)
 {
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    return overlay->hwfuncs->Lock(_this, overlay);
+    void *pixels;
+    int pitch;
+    if (SDL_LockTexture(overlay->hwdata->textureID, NULL, 1, &pixels, &pitch)
+        < 0) {
+        return -1;
+    }
+    switch (overlay->format) {
+    case SDL_YV12_OVERLAY:
+    case SDL_IYUV_OVERLAY:
+        overlay->pixels[0] = (Uint8 *) pixels;
+        overlay->pixels[1] =
+            overlay->pixels[0] + overlay->pitches[0] * overlay->h;
+        overlay->pixels[2] =
+            overlay->pixels[1] + overlay->pitches[1] * overlay->h;
+        break;
+    case SDL_YUY2_OVERLAY:
+    case SDL_UYVY_OVERLAY:
+    case SDL_YVYU_OVERLAY:
+        overlay->pixels[0] = (Uint8 *) pixels;
+        break;
+    }
+    return 0;
 }
 
 void
 SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
 {
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    overlay->hwfuncs->Unlock(_this, overlay);
+    SDL_UnlockTexture(overlay->hwdata->textureID);
 }
 
 int
 SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
 {
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
-    SDL_Rect src, dst;
-    int srcx, srcy, srcw, srch;
-    int dstx, dsty, dstw, dsth;
-
-    /* Clip the rectangle to the screen area */
-    srcx = 0;
-    srcy = 0;
-    srcw = overlay->w;
-    srch = overlay->h;
-    dstx = dstrect->x;
-    dsty = dstrect->y;
-    dstw = dstrect->w;
-    dsth = dstrect->h;
-    if (dstx < 0) {
-        srcw += (dstx * overlay->w) / dstrect->w;
-        dstw += dstx;
-        srcx -= (dstx * overlay->w) / dstrect->w;
-        dstx = 0;
-    }
-    if ((dstx + dstw) > SDL_VideoSurface->w) {
-        int extra = (dstx + dstw - SDL_VideoSurface->w);
-        srcw -= (extra * overlay->w) / dstrect->w;
-        dstw -= extra;
+    if (SDL_RenderCopy(overlay->hwdata->textureID, NULL, dstrect,
+                       SDL_TextureBlendMode_None,
+                       SDL_TextureScaleMode_Fast) < 0) {
+        return -1;
     }
-    if (dsty < 0) {
-        srch += (dsty * overlay->h) / dstrect->h;
-        dsth += dsty;
-        srcy -= (dsty * overlay->h) / dstrect->h;
-        dsty = 0;
-    }
-    if ((dsty + dsth) > SDL_VideoSurface->h) {
-        int extra = (dsty + dsth - SDL_VideoSurface->h);
-        srch -= (extra * overlay->h) / dstrect->h;
-        dsth -= extra;
-    }
-    if (srcw <= 0 || srch <= 0 || srch <= 0 || dsth <= 0) {
-        return 0;
-    }
-    /* Ugh, I can't wait for SDL_Rect to be int values */
-    src.x = srcx;
-    src.y = srcy;
-    src.w = srcw;
-    src.h = srch;
-    dst.x = dstx;
-    dst.y = dsty;
-    dst.w = dstw;
-    dst.h = dsth;
-    return overlay->hwfuncs->Display(_this, overlay, &src, &dst);
+    SDL_RenderPresent();
 }
 
 void
 SDL_FreeYUVOverlay(SDL_Overlay * overlay)
 {
-    SDL_VideoDevice *_this = SDL_GetVideoDevice();
     if (overlay) {
-        if (overlay->hwfuncs) {
-            overlay->hwfuncs->FreeHW(_this, overlay);
+        if (overlay->hwdata) {
+            if (overlay->hwdata->textureID) {
+                SDL_DestroyTexture(overlay->hwdata->textureID);
+            }
+            SDL_free(overlay->hwdata);
         }
         SDL_free(overlay);
     }
 }
-#endif
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_renderer_sw.c	Sat Jun 17 06:45:14 2006 +0000
+++ b/src/video/SDL_renderer_sw.c	Sun Jun 18 06:35:41 2006 +0000
@@ -23,6 +23,7 @@
 
 #include "SDL_video.h"
 #include "SDL_sysvideo.h"
+#include "SDL_yuv_sw_c.h"
 
 
 /* SDL surface based renderer implementation */
@@ -205,29 +206,30 @@
 static int
 SDL_SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
-    SDL_Surface *surface;
-    int bpp;
-    Uint32 Rmask, Gmask, Bmask, Amask;
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        if (texture->access == SDL_TextureAccess_Render) {
+            SDL_SetError("Rendering to YUV format textures is not supported");
+            return -1;
+        }
+        texture->driverdata = SDL_SW_CreateYUVTexture(texture);
+    } else {
+        int bpp;
+        Uint32 Rmask, Gmask, Bmask, Amask;
 
-    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
-        /* FIXME: implement this */
-        return -1;
+        if (!SDL_PixelFormatEnumToMasks
+            (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
+            SDL_SetError("Unknown texture format");
+            return -1;
+        }
+
+        texture->driverdata =
+            SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
+                                 Bmask, Amask);
     }
 
-    if (!SDL_PixelFormatEnumToMasks
-        (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
-        SDL_SetError("Unknown texture format");
+    if (!texture->driverdata) {
         return -1;
     }
-
-    surface =
-        SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
-                             Bmask, Amask);
-    if (!surface) {
-        return -1;
-    }
-
-    texture->driverdata = surface;
     return 0;
 }
 
@@ -235,11 +237,16 @@
 SDL_SW_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
                           void **pixels, int *pitch)
 {
-    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        return SDL_SW_QueryYUVTexturePixels((SDL_SW_YUVTexture *) texture->
+                                            driverdata, pixels, pitch);
+    } else {
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
 
-    *pixels = surface->pixels;
-    *pitch = surface->pitch;
-    return 0;
+        *pixels = surface->pixels;
+        *pitch = surface->pitch;
+        return 0;
+    }
 }
 
 static int
@@ -247,43 +254,58 @@
                          const SDL_Color * colors, int firstcolor,
                          int ncolors)
 {
-    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        SDL_SetError("YUV textures don't have a palette");
+        return -1;
+    } else {
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
 
-    return SDL_SetPaletteColors(surface->format->palette, colors, firstcolor,
-                                ncolors);
+        return SDL_SetPaletteColors(surface->format->palette, colors,
+                                    firstcolor, ncolors);
+    }
 }
 
 static int
 SDL_SW_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
                          SDL_Color * colors, int firstcolor, int ncolors)
 {
-    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        SDL_SetError("YUV textures don't have a palette");
+        return -1;
+    } else {
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
 
-    SDL_memcpy(colors, &surface->format->palette->colors[firstcolor],
-               ncolors * sizeof(*colors));
-    return 0;
+        SDL_memcpy(colors, &surface->format->palette->colors[firstcolor],
+                   ncolors * sizeof(*colors));
+        return 0;
+    }
 }
 
 static int
 SDL_SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                      const SDL_Rect * rect, const void *pixels, int pitch)
 {
-    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
-    Uint8 *src, *dst;
-    int row;
-    size_t length;
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        return SDL_SW_UpdateYUVTexture((SDL_SW_YUVTexture *) texture->
+                                       driverdata, rect, pixels, pitch);
+    } else {
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+        Uint8 *src, *dst;
+        int row;
+        size_t length;
 
-    src = (Uint8 *) pixels;
-    dst =
-        (Uint8 *) surface->pixels + rect->y * surface->pitch +
-        rect->x * surface->format->BytesPerPixel;
-    length = rect->w * surface->format->BytesPerPixel;
-    for (row = 0; row < rect->h; ++row) {
-        SDL_memcpy(dst, src, length);
-        src += pitch;
-        dst += surface->pitch;
+        src = (Uint8 *) pixels;
+        dst =
+            (Uint8 *) surface->pixels + rect->y * surface->pitch +
+            rect->x * surface->format->BytesPerPixel;
+        length = rect->w * surface->format->BytesPerPixel;
+        for (row = 0; row < rect->h; ++row) {
+            SDL_memcpy(dst, src, length);
+            src += pitch;
+            dst += surface->pitch;
+        }
+        return 0;
     }
-    return 0;
 }
 
 static int
@@ -291,18 +313,27 @@
                    const SDL_Rect * rect, int markDirty, void **pixels,
                    int *pitch)
 {
-    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        return SDL_SW_LockYUVTexture((SDL_SW_YUVTexture *) texture->
+                                     driverdata, rect, markDirty, pixels,
+                                     pitch);
+    } else {
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
 
-    *pixels =
-        (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
-                  rect->x * surface->format->BytesPerPixel);
-    *pitch = surface->pitch;
-    return 0;
+        *pixels =
+            (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
+                      rect->x * surface->format->BytesPerPixel);
+        *pitch = surface->pitch;
+        return 0;
+    }
 }
 
 static void
 SDL_SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        SDL_SW_UnlockYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
+    }
 }
 
 static void
@@ -346,22 +377,36 @@
                   int blendMode, int scaleMode)
 {
     SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata;
-    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
-    SDL_Rect real_srcrect = *srcrect;
-    SDL_Rect real_dstrect = *dstrect;
 
-    if (blendMode & (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) {
-        SDL_SetAlpha(surface, SDL_SRCALPHA, 0);
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        SDL_Surface *target = data->target;
+        void *pixels =
+            (Uint8 *) target->pixels + dstrect->y * target->pitch +
+            dstrect->x * target->format->BytesPerPixel;
+        return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
+                                   srcrect,
+                                   renderer->window->display->current_mode.
+                                   format, dstrect->w, dstrect->h, pixels,
+                                   target->pitch);
     } else {
-        SDL_SetAlpha(surface, 0, 0);
-    }
-    if (scaleMode != SDL_TextureScaleMode_None &&
-        (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) {
-        return SDL_SoftStretch(surface, &real_srcrect, data->target,
-                               &real_dstrect);
-    } else {
-        return SDL_LowerBlit(surface, &real_srcrect, data->target,
-                             &real_dstrect);
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+        SDL_Rect real_srcrect = *srcrect;
+        SDL_Rect real_dstrect = *dstrect;
+
+        if (blendMode &
+            (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) {
+            SDL_SetAlpha(surface, SDL_SRCALPHA, 0);
+        } else {
+            SDL_SetAlpha(surface, 0, 0);
+        }
+        if (scaleMode != SDL_TextureScaleMode_None &&
+            (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) {
+            return SDL_SoftStretch(surface, &real_srcrect, data->target,
+                                   &real_dstrect);
+        } else {
+            return SDL_LowerBlit(surface, &real_srcrect, data->target,
+                                 &real_dstrect);
+        }
     }
 }
 
@@ -446,9 +491,13 @@
 static void
 SDL_SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
-    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        SDL_SW_DestroyYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
+    } else {
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
 
-    SDL_FreeSurface(surface);
+        SDL_FreeSurface(surface);
+    }
 }
 
 static void
--- a/src/video/SDL_video.c	Sat Jun 17 06:45:14 2006 +0000
+++ b/src/video/SDL_video.c	Sun Jun 18 06:35:41 2006 +0000
@@ -567,7 +567,7 @@
         ncolors = 0;
     }
     if ((!ncolors && display->palette) || (ncolors && !display->palette)
-        || (ncolors != display->palette->ncolors)) {
+        || (ncolors && ncolors != display->palette->ncolors)) {
         if (display->palette) {
             SDL_FreePalette(display->palette);
             display->palette = NULL;
@@ -1434,6 +1434,7 @@
 {
     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
     SDL_Renderer *renderer;
+    SDL_Rect full_rect;
 
     if (!texture) {
         return -1;
@@ -1443,6 +1444,15 @@
     if (!renderer->UpdateTexture) {
         return -1;
     }
+
+    if (!rect) {
+        full_rect.x = 0;
+        full_rect.y = 0;
+        full_rect.w = texture->w;
+        full_rect.h = texture->h;
+        rect = &full_rect;
+    }
+
     return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
 }
 
@@ -1452,6 +1462,7 @@
 {
     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
     SDL_Renderer *renderer;
+    SDL_Rect full_rect;
 
     if (!texture) {
         return -1;
@@ -1461,6 +1472,15 @@
     if (!renderer->LockTexture) {
         return -1;
     }
+
+    if (!rect) {
+        full_rect.x = 0;
+        full_rect.y = 0;
+        full_rect.w = texture->w;
+        full_rect.h = texture->h;
+        rect = &full_rect;
+    }
+
     return renderer->LockTexture(renderer, texture, rect, markDirty, pixels,
                                  pitch);
 }
@@ -1520,6 +1540,7 @@
 SDL_RenderFill(const SDL_Rect * rect, Uint32 color)
 {
     SDL_Renderer *renderer;
+    SDL_Rect full_rect;
 
     if (!_this) {
         return -1;
@@ -1530,6 +1551,14 @@
         return -1;
     }
 
+    if (!rect) {
+        full_rect.x = 0;
+        full_rect.y = 0;
+        full_rect.w = renderer->window->w;
+        full_rect.h = renderer->window->h;
+        rect = &full_rect;
+    }
+
     renderer->RenderFill(renderer, rect, color);
 }
 
@@ -1539,6 +1568,8 @@
 {
     SDL_Texture *texture = SDL_GetTextureFromID(textureID);
     SDL_Renderer *renderer;
+    SDL_Rect full_srcrect;
+    SDL_Rect full_dstrect;
 
     if (!texture || texture->renderer != SDL_CurrentDisplay.current_renderer) {
         return;
@@ -1549,6 +1580,21 @@
         return -1;
     }
 
+    if (!srcrect) {
+        full_srcrect.x = 0;
+        full_srcrect.y = 0;
+        full_srcrect.w = texture->w;
+        full_srcrect.h = texture->h;
+        srcrect = &full_srcrect;
+    }
+    if (!dstrect) {
+        full_dstrect.x = 0;
+        full_dstrect.y = 0;
+        full_dstrect.w = renderer->window->w;
+        full_dstrect.h = renderer->window->h;
+        dstrect = &full_dstrect;
+    }
+
     return renderer->RenderCopy(renderer, texture, srcrect, dstrect,
                                 blendMode, scaleMode);
 }
@@ -1557,6 +1603,7 @@
 SDL_RenderReadPixels(const SDL_Rect * rect, void *pixels, int pitch)
 {
     SDL_Renderer *renderer;
+    SDL_Rect full_rect;
 
     if (!_this) {
         return -1;
@@ -1567,6 +1614,14 @@
         return -1;
     }
 
+    if (!rect) {
+        full_rect.x = 0;
+        full_rect.y = 0;
+        full_rect.w = renderer->window->w;
+        full_rect.h = renderer->window->h;
+        rect = &full_rect;
+    }
+
     return renderer->RenderReadPixels(renderer, rect, pixels, pitch);
 }
 
@@ -1574,6 +1629,7 @@
 SDL_RenderWritePixels(const SDL_Rect * rect, const void *pixels, int pitch)
 {
     SDL_Renderer *renderer;
+    SDL_Rect full_rect;
 
     if (!_this) {
         return -1;
@@ -1584,6 +1640,14 @@
         return -1;
     }
 
+    if (!rect) {
+        full_rect.x = 0;
+        full_rect.y = 0;
+        full_rect.w = renderer->window->w;
+        full_rect.h = renderer->window->h;
+        rect = &full_rect;
+    }
+
     return renderer->RenderWritePixels(renderer, rect, pixels, pitch);
 }
 
--- a/src/video/SDL_yuv_sw.c	Sat Jun 17 06:45:14 2006 +0000
+++ b/src/video/SDL_yuv_sw.c	Sun Jun 18 06:35:41 2006 +0000
@@ -21,8 +21,7 @@
 */
 #include "SDL_config.h"
 
-#if 0                           /* TODO */
-/* This is the software implementation of the YUV video overlay support */
+/* This is the software implementation of the YUV texture support */
 
 /* This code was derived from code carrying the following copyright notices:
 
@@ -87,22 +86,14 @@
 #include "SDL_video.h"
 #include "SDL_cpuinfo.h"
 #include "SDL_stretch_c.h"
-#include "SDL_yuvfuncs.h"
 #include "SDL_yuv_sw_c.h"
 
-/* The functions used to manipulate software video overlays */
-static struct private_yuvhwfuncs sw_yuvfuncs = {
-    SDL_LockYUV_SW,
-    SDL_UnlockYUV_SW,
-    SDL_DisplayYUV_SW,
-    SDL_FreeYUV_SW
-};
 
-/* RGB conversion lookup tables */
-struct private_yuvhwdata
+struct SDL_SW_YUVTexture
 {
-    SDL_Surface *stretch;
-    SDL_Surface *display;
+    SDL_Texture *texture;
+
+    Uint32 target_format;
     Uint8 *pixels;
     int *colortab;
     Uint32 *rgb_2_pix;
@@ -118,9 +109,12 @@
     /* These are just so we don't have to allocate them separately */
     Uint16 pitches[3];
     Uint8 *planes[3];
+
+    /* This is a temporary surface in case we have to stretch copy */
+    SDL_Surface *stretch;
+    SDL_Surface *display;
 };
 
-
 /* The colorspace conversion functions */
 
 #if 0                           /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
@@ -918,105 +912,30 @@
     return 1 + free_bits_at_bottom(a >> 1);
 }
 
-
-SDL_Overlay *
-SDL_CreateYUV_SW(_THIS, int width, int height, Uint32 format,
-                 SDL_Surface * display)
+static int
+SDL_SW_SetupYUVDisplay(SDL_SW_YUVTexture * swdata, Uint32 target_format)
 {
-    SDL_Overlay *overlay;
-    struct private_yuvhwdata *swdata;
-    int *Cr_r_tab;
-    int *Cr_g_tab;
-    int *Cb_g_tab;
-    int *Cb_b_tab;
     Uint32 *r_2_pix_alloc;
     Uint32 *g_2_pix_alloc;
     Uint32 *b_2_pix_alloc;
     int i;
-    int CR, CB;
-    Uint32 Rmask, Gmask, Bmask;
-
-    /* Only RGB packed pixel conversion supported */
-    if ((display->format->BytesPerPixel != 2) &&
-        (display->format->BytesPerPixel != 3) &&
-        (display->format->BytesPerPixel != 4)) {
-        SDL_SetError("Can't use YUV data on non 16/24/32 bit surfaces");
-        return (NULL);
-    }
+    int bpp;
+    Uint32 Rmask, Gmask, Bmask, Amask;
 
-    /* Verify that we support the format */
-    switch (format) {
-    case SDL_YV12_OVERLAY:
-    case SDL_IYUV_OVERLAY:
-    case SDL_YUY2_OVERLAY:
-    case SDL_UYVY_OVERLAY:
-    case SDL_YVYU_OVERLAY:
-        break;
-    default:
-        SDL_SetError("Unsupported YUV format");
-        return (NULL);
+    if (!SDL_PixelFormatEnumToMasks
+        (target_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask) || bpp < 15) {
+        SDL_SetError("Unsupported YUV destination format");
+        return -1;
     }
 
-    /* Create the overlay structure */
-    overlay = (SDL_Overlay *) SDL_malloc(sizeof *overlay);
-    if (overlay == NULL) {
-        SDL_OutOfMemory();
-        return (NULL);
-    }
-    SDL_memset(overlay, 0, (sizeof *overlay));
-
-    /* Fill in the basic members */
-    overlay->format = format;
-    overlay->w = width;
-    overlay->h = height;
-
-    /* Set up the YUV surface function structure */
-    overlay->hwfuncs = &sw_yuvfuncs;
-
-    /* Create the pixel data and lookup tables */
-    swdata = (struct private_yuvhwdata *) SDL_malloc(sizeof *swdata);
-    overlay->hwdata = swdata;
-    if (swdata == NULL) {
-        SDL_OutOfMemory();
-        SDL_FreeYUVOverlay(overlay);
-        return (NULL);
-    }
-    swdata->stretch = NULL;
-    swdata->display = display;
-    swdata->pixels = (Uint8 *) SDL_malloc(width * height * 2);
-    swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
-    Cr_r_tab = &swdata->colortab[0 * 256];
-    Cr_g_tab = &swdata->colortab[1 * 256];
-    Cb_g_tab = &swdata->colortab[2 * 256];
-    Cb_b_tab = &swdata->colortab[3 * 256];
-    swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
+    swdata->target_format = target_format;
     r_2_pix_alloc = &swdata->rgb_2_pix[0 * 768];
     g_2_pix_alloc = &swdata->rgb_2_pix[1 * 768];
     b_2_pix_alloc = &swdata->rgb_2_pix[2 * 768];
-    if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
-        SDL_OutOfMemory();
-        SDL_FreeYUVOverlay(overlay);
-        return (NULL);
-    }
-
-    /* Generate the tables for the display surface */
-    for (i = 0; i < 256; i++) {
-        /* Gamma correction (luminescence table) and chroma correction
-           would be done here.  See the Berkeley mpeg_play sources.
-         */
-        CB = CR = (i - 128);
-        Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
-        Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
-        Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
-        Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
-    }
 
     /* 
      * Set up entries 0-255 in rgb-to-pixel value tables.
      */
-    Rmask = display->format->Rmask;
-    Gmask = display->format->Gmask;
-    Bmask = display->format->Bmask;
     for (i = 0; i < 256; ++i) {
         r_2_pix_alloc[i + 256] = i >> (8 - number_of_bits_set(Rmask));
         r_2_pix_alloc[i + 256] <<= free_bits_at_bottom(Rmask);
@@ -1033,7 +952,7 @@
      * harmless in the normal case as storing a 32-bit value
      * through a short pointer will lose the top bits anyway.
      */
-    if (display->format->BytesPerPixel == 2) {
+    if (SDL_BYTESPERPIXEL(target_format) == 2) {
         for (i = 0; i < 256; ++i) {
             r_2_pix_alloc[i + 256] |= (r_2_pix_alloc[i + 256]) << 16;
             g_2_pix_alloc[i + 256] |= (g_2_pix_alloc[i + 256]) << 16;
@@ -1055,10 +974,10 @@
     }
 
     /* You have chosen wisely... */
-    switch (format) {
-    case SDL_YV12_OVERLAY:
-    case SDL_IYUV_OVERLAY:
-        if (display->format->BytesPerPixel == 2) {
+    switch (swdata->texture->format) {
+    case SDL_PixelFormat_YV12:
+    case SDL_PixelFormat_IYUV:
+        if (SDL_BYTESPERPIXEL(target_format) == 2) {
 #if 0                           /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
             /* inline assembly functions */
             if (SDL_HasMMX() && (Rmask == 0xF800) &&
@@ -1074,11 +993,11 @@
 #endif
             swdata->Display2X = Color16DitherYV12Mod2X;
         }
-        if (display->format->BytesPerPixel == 3) {
+        if (SDL_BYTESPERPIXEL(target_format) == 3) {
             swdata->Display1X = Color24DitherYV12Mod1X;
             swdata->Display2X = Color24DitherYV12Mod2X;
         }
-        if (display->format->BytesPerPixel == 4) {
+        if (SDL_BYTESPERPIXEL(target_format) == 4) {
 #if 0                           /*defined(__GNUC__) && defined(__i386__) && SDL_ASSEMBLY_ROUTINES */
             /* inline assembly functions */
             if (SDL_HasMMX() && (Rmask == 0x00FF0000) &&
@@ -1096,18 +1015,18 @@
             swdata->Display2X = Color32DitherYV12Mod2X;
         }
         break;
-    case SDL_YUY2_OVERLAY:
-    case SDL_UYVY_OVERLAY:
-    case SDL_YVYU_OVERLAY:
-        if (display->format->BytesPerPixel == 2) {
+    case SDL_PixelFormat_YUY2:
+    case SDL_PixelFormat_UYVY:
+    case SDL_PixelFormat_YVYU:
+        if (SDL_BYTESPERPIXEL(target_format) == 2) {
             swdata->Display1X = Color16DitherYUY2Mod1X;
             swdata->Display2X = Color16DitherYUY2Mod2X;
         }
-        if (display->format->BytesPerPixel == 3) {
+        if (SDL_BYTESPERPIXEL(target_format) == 3) {
             swdata->Display1X = Color24DitherYUY2Mod1X;
             swdata->Display2X = Color24DitherYUY2Mod2X;
         }
-        if (display->format->BytesPerPixel == 4) {
+        if (SDL_BYTESPERPIXEL(target_format) == 4) {
             swdata->Display1X = Color32DitherYUY2Mod1X;
             swdata->Display2X = Color32DitherYUY2Mod2X;
         }
@@ -1117,28 +1036,88 @@
         break;
     }
 
+    if (swdata->display) {
+        SDL_FreeSurface(swdata->display);
+        swdata->display = NULL;
+    }
+    return 0;
+}
+
+SDL_SW_YUVTexture *
+SDL_SW_CreateYUVTexture(SDL_Texture * texture)
+{
+    SDL_SW_YUVTexture *swdata;
+    int *Cr_r_tab;
+    int *Cr_g_tab;
+    int *Cb_g_tab;
+    int *Cb_b_tab;
+    int i;
+    int CR, CB;
+
+    swdata = (SDL_SW_YUVTexture *) SDL_malloc(sizeof(*swdata));
+    if (!swdata) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+    SDL_zerop(swdata);
+
+    switch (texture->format) {
+    case SDL_PixelFormat_YV12:
+    case SDL_PixelFormat_IYUV:
+    case SDL_PixelFormat_YUY2:
+    case SDL_PixelFormat_UYVY:
+    case SDL_PixelFormat_YVYU:
+        break;
+    default:
+        SDL_SetError("Unsupported YUV format");
+        return NULL;
+    }
+
+    swdata->texture = texture;
+    swdata->target_format = SDL_PixelFormat_Unknown;
+    swdata->pixels = (Uint8 *) SDL_malloc(texture->w * texture->h * 2);
+    swdata->colortab = (int *) SDL_malloc(4 * 256 * sizeof(int));
+    swdata->rgb_2_pix = (Uint32 *) SDL_malloc(3 * 768 * sizeof(Uint32));
+    if (!swdata->pixels || !swdata->colortab || !swdata->rgb_2_pix) {
+        SDL_OutOfMemory();
+        SDL_SW_DestroyYUVTexture(swdata);
+        return NULL;
+    }
+
+    /* Generate the tables for the display surface */
+    Cr_r_tab = &swdata->colortab[0 * 256];
+    Cr_g_tab = &swdata->colortab[1 * 256];
+    Cb_g_tab = &swdata->colortab[2 * 256];
+    Cb_b_tab = &swdata->colortab[3 * 256];
+    for (i = 0; i < 256; i++) {
+        /* Gamma correction (luminescence table) and chroma correction
+           would be done here.  See the Berkeley mpeg_play sources.
+         */
+        CB = CR = (i - 128);
+        Cr_r_tab[i] = (int) ((0.419 / 0.299) * CR);
+        Cr_g_tab[i] = (int) (-(0.299 / 0.419) * CR);
+        Cb_g_tab[i] = (int) (-(0.114 / 0.331) * CB);
+        Cb_b_tab[i] = (int) ((0.587 / 0.331) * CB);
+    }
+
     /* Find the pitch and offset values for the overlay */
-    overlay->pitches = swdata->pitches;
-    overlay->pixels = swdata->planes;
-    switch (format) {
-    case SDL_YV12_OVERLAY:
-    case SDL_IYUV_OVERLAY:
-        overlay->pitches[0] = overlay->w;
-        overlay->pitches[1] = overlay->pitches[0] / 2;
-        overlay->pitches[2] = overlay->pitches[0] / 2;
-        overlay->pixels[0] = swdata->pixels;
-        overlay->pixels[1] = overlay->pixels[0] +
-            overlay->pitches[0] * overlay->h;
-        overlay->pixels[2] = overlay->pixels[1] +
-            overlay->pitches[1] * overlay->h / 2;
-        overlay->planes = 3;
+    switch (texture->format) {
+    case SDL_PixelFormat_YV12:
+    case SDL_PixelFormat_IYUV:
+        swdata->pitches[0] = texture->w;
+        swdata->pitches[1] = swdata->pitches[0] / 2;
+        swdata->pitches[2] = swdata->pitches[0] / 2;
+        swdata->planes[0] = swdata->pixels;
+        swdata->planes[1] =
+            swdata->planes[0] + swdata->pitches[0] * texture->h;
+        swdata->planes[2] =
+            swdata->planes[1] + swdata->pitches[1] * texture->h / 2;
         break;
-    case SDL_YUY2_OVERLAY:
-    case SDL_UYVY_OVERLAY:
-    case SDL_YVYU_OVERLAY:
-        overlay->pitches[0] = overlay->w * 2;
-        overlay->pixels[0] = swdata->pixels;
-        overlay->planes = 1;
+    case SDL_PixelFormat_YUY2:
+    case SDL_PixelFormat_UYVY:
+    case SDL_PixelFormat_YVYU:
+        swdata->pitches[0] = texture->w * 2;
+        swdata->planes[0] = swdata->pixels;
         break;
     default:
         /* We should never get here (caught above) */
@@ -1146,146 +1125,210 @@
     }
 
     /* We're all done.. */
-    return (overlay);
+    return (swdata);
 }
 
 int
-SDL_LockYUV_SW(_THIS, SDL_Overlay * overlay)
+SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
+                             int *pitch)
 {
-    return (0);
-}
-
-void
-SDL_UnlockYUV_SW(_THIS, SDL_Overlay * overlay)
-{
-    return;
+    *pixels = swdata->planes[0];
+    *pitch = swdata->pitches[0];
+    return 0;
 }
 
 int
-SDL_DisplayYUV_SW(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
-                  SDL_Rect * dst)
+SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
+                        const void *pixels, int pitch)
 {
-    struct private_yuvhwdata *swdata;
+    SDL_Texture *texture = swdata->texture;
+
+    switch (texture->format) {
+    case SDL_PixelFormat_YV12:
+    case SDL_PixelFormat_IYUV:
+        if (rect
+            && (rect->x != 0 || rect->y != 0 || rect->w != texture->w
+                || rect->h != texture->h)) {
+            SDL_SetError
+                ("YV12 and IYUV textures only support full surface updates");
+            return -1;
+        }
+        SDL_memcpy(swdata->pixels, pixels, texture->h * texture->w * 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 = rect->w * 2;
+            for (row = 0; row < rect->h; ++row) {
+                SDL_memcpy(dst, src, length);
+                src += pitch;
+                dst += swdata->pitches[0];
+            }
+        }
+        break;
+    }
+    return 0;
+}
+
+int
+SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
+                      int markDirty, void **pixels, int *pitch)
+{
+    SDL_Texture *texture = swdata->texture;
+
+    switch (texture->format) {
+    case SDL_PixelFormat_YV12:
+    case SDL_PixelFormat_IYUV:
+        if (rect
+            && (rect->x != 0 || rect->y != 0 || rect->w != texture->w
+                || rect->h != texture->h)) {
+            SDL_SetError
+                ("YV12 and IYUV textures only support full surface locks");
+            return -1;
+        }
+        break;
+    }
+
+    *pixels = swdata->planes[0] + rect->y * swdata->pitches[0] + rect->x * 2;
+    *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)
+{
+    SDL_Texture *texture = swdata->texture;
     int stretch;
     int scale_2x;
-    SDL_Surface *display;
     Uint8 *lum, *Cr, *Cb;
-    Uint8 *dstp;
     int mod;
 
-    swdata = overlay->hwdata;
+    /* Make sure we're set up to display in the desired format */
+    if (target_format != swdata->target_format) {
+        if (SDL_SW_SetupYUVDisplay(swdata, target_format) < 0) {
+            return -1;
+        }
+    }
+
     stretch = 0;
     scale_2x = 0;
-    if (src->x || src->y || src->w < overlay->w || src->h < overlay->h) {
+    if (srcrect->x || srcrect->y || srcrect->w < texture->w
+        || srcrect->h < texture->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 ((src->w != dst->w) || (src->h != dst->h)) {
-        if ((dst->w == 2 * src->w) && (dst->h == 2 * src->h)) {
+    } else if ((srcrect->w != w) || (srcrect->h != h)) {
+        if ((w == 2 * srcrect->w) && (h == 2 * srcrect->h)) {
             scale_2x = 1;
         } else {
             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) {
-            display = swdata->display;
-            swdata->stretch = SDL_CreateRGBSurface(0,
-                                                   overlay->w,
-                                                   overlay->h,
-                                                   display->format->
-                                                   BitsPerPixel,
-                                                   display->format->
-                                                   Rmask,
-                                                   display->format->
-                                                   Gmask,
-                                                   display->format->Bmask, 0);
+            /* This must have succeeded in SDL_SW_SetupYUVDisplay() earlier */
+            SDL_PixelFormatEnumToMasks(target_format, &bpp, &Rmask, &Gmask,
+                                       &Bmask, &Amask);
+            swdata->stretch =
+                SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask,
+                                     Gmask, Bmask, Amask);
             if (!swdata->stretch) {
                 return (-1);
             }
         }
-        display = swdata->stretch;
-    } else {
-        display = swdata->display;
+        pixels = swdata->stretch->pixels;
+        pitch = swdata->stretch->pitch;
     }
-    switch (overlay->format) {
-    case SDL_YV12_OVERLAY:
-        lum = overlay->pixels[0];
-        Cr = overlay->pixels[1];
-        Cb = overlay->pixels[2];
+    switch (texture->format) {
+    case SDL_PixelFormat_YV12:
+        lum = swdata->planes[0];
+        Cr = swdata->planes[1];
+        Cb = swdata->planes[2];
         break;
-    case SDL_IYUV_OVERLAY:
-        lum = overlay->pixels[0];
-        Cr = overlay->pixels[2];
-        Cb = overlay->pixels[1];
+    case SDL_PixelFormat_IYUV:
+        lum = swdata->planes[0];
+        Cr = swdata->planes[2];
+        Cb = swdata->planes[1];
         break;
-    case SDL_YUY2_OVERLAY:
-        lum = overlay->pixels[0];
+    case SDL_PixelFormat_YUY2:
+        lum = swdata->planes[0];
         Cr = lum + 3;
         Cb = lum + 1;
         break;
-    case SDL_UYVY_OVERLAY:
-        lum = overlay->pixels[0] + 1;
+    case SDL_PixelFormat_UYVY:
+        lum = swdata->planes[0] + 1;
         Cr = lum + 1;
         Cb = lum - 1;
         break;
-    case SDL_YVYU_OVERLAY:
-        lum = overlay->pixels[0];
+    case SDL_PixelFormat_YVYU:
+        lum = swdata->planes[0];
         Cr = lum + 1;
         Cb = lum + 3;
         break;
     default:
-        SDL_SetError("Unsupported YUV format in blit");
+        SDL_SetError("Unsupported YUV format in copy");
         return (-1);
     }
-    if (SDL_MUSTLOCK(display)) {
-        if (SDL_LockSurface(display) < 0) {
-            return (-1);
-        }
-    }
-    if (stretch) {
-        dstp = (Uint8 *) swdata->stretch->pixels;
-    } else {
-        dstp = (Uint8 *) display->pixels
-            + dst->x * display->format->BytesPerPixel
-            + dst->y * display->pitch;
-    }
-    mod = (display->pitch / display->format->BytesPerPixel);
+    mod = (pitch / SDL_BYTESPERPIXEL(target_format));
 
     if (scale_2x) {
-        mod -= (overlay->w * 2);
+        mod -= (texture->w * 2);
         swdata->Display2X(swdata->colortab, swdata->rgb_2_pix,
-                          lum, Cr, Cb, dstp, overlay->h, overlay->w, mod);
+                          lum, Cr, Cb, pixels, texture->h, texture->w, mod);
     } else {
-        mod -= overlay->w;
+        mod -= texture->w;
         swdata->Display1X(swdata->colortab, swdata->rgb_2_pix,
-                          lum, Cr, Cb, dstp, overlay->h, overlay->w, mod);
-    }
-    if (SDL_MUSTLOCK(display)) {
-        SDL_UnlockSurface(display);
+                          lum, Cr, Cb, pixels, texture->h, texture->w, mod);
     }
     if (stretch) {
-        display = swdata->display;
-        SDL_SoftStretch(swdata->stretch, src, display, dst);
+        SDL_Rect rect = *srcrect;
+        SDL_SoftStretch(swdata->stretch, &rect, swdata->display, NULL);
     }
-    SDL_UpdateRects(display, 1, dst);
-
-    return (0);
+    return 0;
 }
 
 void
-SDL_FreeYUV_SW(_THIS, SDL_Overlay * overlay)
+SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata)
 {
-    struct private_yuvhwdata *swdata;
-
-    swdata = overlay->hwdata;
     if (swdata) {
-        if (swdata->stretch) {
-            SDL_FreeSurface(swdata->stretch);
-        }
         if (swdata->pixels) {
             SDL_free(swdata->pixels);
         }
@@ -1295,9 +1338,14 @@
         if (swdata->rgb_2_pix) {
             SDL_free(swdata->rgb_2_pix);
         }
+        if (swdata->stretch) {
+            SDL_FreeSurface(swdata->stretch);
+        }
+        if (swdata->display) {
+            SDL_FreeSurface(swdata->display);
+        }
         SDL_free(swdata);
     }
 }
-#endif /* TODO */
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_yuv_sw_c.h	Sat Jun 17 06:45:14 2006 +0000
+++ b/src/video/SDL_yuv_sw_c.h	Sun Jun 18 06:35:41 2006 +0000
@@ -24,17 +24,21 @@
 #include "SDL_video.h"
 #include "SDL_sysvideo.h"
 
-/* This is the software implementation of the YUV video overlay support */
+/* This is the software implementation of the YUV texture support */
 
-extern SDL_Overlay *SDL_CreateYUV_SW(_THIS, int width, int height,
-                                     Uint32 format, SDL_Surface * display);
-
-extern int SDL_LockYUV_SW(_THIS, SDL_Overlay * overlay);
+typedef struct SDL_SW_YUVTexture SDL_SW_YUVTexture;
 
-extern void SDL_UnlockYUV_SW(_THIS, SDL_Overlay * overlay);
+SDL_SW_YUVTexture *SDL_SW_CreateYUVTexture(SDL_Texture * texture);
+int SDL_SW_QueryYUVTexturePixels(SDL_SW_YUVTexture * swdata, void **pixels,
+                                 int *pitch);
+int SDL_SW_UpdateYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
+                            const void *pixels, int pitch);
+int SDL_SW_LockYUVTexture(SDL_SW_YUVTexture * swdata, const SDL_Rect * rect,
+                          int markDirty, void **pixels, int *pitch);
+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);
+void SDL_SW_DestroyYUVTexture(SDL_SW_YUVTexture * swdata);
 
-extern int SDL_DisplayYUV_SW(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
-                             SDL_Rect * dst);
-
-extern void SDL_FreeYUV_SW(_THIS, SDL_Overlay * overlay);
 /* vi: set ts=4 sw=4 expandtab: */