diff src/SDL_compat.c @ 1684:c4aa1a2f48f1 SDL-1.3

Software YUV texture support in progress...
author Sam Lantinga <slouken@libsdl.org>
date Sun, 18 Jun 2006 06:35:41 +0000
parents 396a35389351
children 66267c6a0b12
line wrap: on
line diff
--- 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: */