Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Software YUV texture support in progress...
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Jun 18, 2006
1 parent 5d97336 commit 8e86df9
Show file tree
Hide file tree
Showing 6 changed files with 576 additions and 368 deletions.
15 changes: 10 additions & 5 deletions include/SDL_pixels.h
Expand Up @@ -179,11 +179,16 @@ enum
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
Expand Down
190 changes: 114 additions & 76 deletions src/SDL_compat.c
Expand Up @@ -1176,121 +1176,159 @@ SDL_ResetCursor(void)
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;
}
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);

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;
}
/* If hardware YUV overlay failed ... */
if (overlay == NULL) {
overlay = SDL_CreateYUV_SW(_this, w, h, format, display);

overlay = (SDL_Overlay *) SDL_malloc(sizeof(*overlay));
if (!overlay) {
SDL_OutOfMemory();
return NULL;
}
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;
}
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 (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;
if (SDL_RenderCopy(overlay->hwdata->textureID, NULL, dstrect,
SDL_TextureBlendMode_None,
SDL_TextureScaleMode_Fast) < 0) {
return -1;
}
/* 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: */

0 comments on commit 8e86df9

Please sign in to comment.