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_DEFINE_PIXELFORMAT(SDL_PixelType_Packed32, SDL_PackedOrder_ARGB,
SDL_PackedLayout_2101010, 32, 4), SDL_PackedLayout_2101010, 32, 4),


SDL_PixelFormat_YV12 = SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'), SDL_PixelFormat_YV12 = /* Planar mode: Y + V + U (3 planes) */
SDL_PixelFormat_IYUV = SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'), SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
SDL_PixelFormat_YUY2 = SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'), SDL_PixelFormat_IYUV = /* Planar mode: Y + U + V (3 planes) */
SDL_PixelFormat_UYVY = SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'), SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'),
SDL_PixelFormat_YVYU = SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'), 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 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); SDL_memset(SDL_cursor->save[0], 0, savelen);
} }
} }
#endif

struct private_yuvhwdata
{
Uint16 pitches[3];
Uint8 *planes[3];

SDL_TextureID textureID;
};


SDL_Overlay * SDL_Overlay *
SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display) 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; SDL_Overlay *overlay;
Uint32 texture_format;


window = SDL_GetWindowFromSurface(display); if ((display->flags & SDL_OPENGL) == SDL_OPENGL) {
if (window && (window->flags & SDL_WINDOW_OPENGL)) {
SDL_SetError("YUV overlays are not supported in OpenGL mode"); SDL_SetError("YUV overlays are not supported in OpenGL mode");
return NULL; return NULL;
} }


/* Display directly on video surface, if possible */ if (display != SDL_PublicSurface) {
if (SDL_getenv("SDL_VIDEO_YUV_DIRECT")) { SDL_SetError("YUV display is only supported on the screen surface");
if (window && return NULL;
((window->surface->format->BytesPerPixel == 2) ||
(window->surface->format->BytesPerPixel == 4))) {
display = window->surface;
}
} }
overlay = NULL;
yuv_hwaccel = SDL_getenv("SDL_VIDEO_YUV_HWACCEL"); switch (format) {
if (((display->flags & SDL_SCREEN_SURFACE) && _this->CreateYUVOverlay) && case SDL_YV12_OVERLAY:
(!yuv_hwaccel || (SDL_atoi(yuv_hwaccel) > 0))) { texture_format = SDL_PixelFormat_YV12;
overlay = _this->CreateYUVOverlay(_this, w, h, format, display); 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_Overlay *) SDL_malloc(sizeof(*overlay));
overlay = SDL_CreateYUV_SW(_this, w, h, format, display); 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; return overlay;
} }


int int
SDL_LockYUVOverlay(SDL_Overlay * overlay) SDL_LockYUVOverlay(SDL_Overlay * overlay)
{ {
SDL_VideoDevice *_this = SDL_GetVideoDevice(); void *pixels;
return overlay->hwfuncs->Lock(_this, overlay); 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 void
SDL_UnlockYUVOverlay(SDL_Overlay * overlay) SDL_UnlockYUVOverlay(SDL_Overlay * overlay)
{ {
SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_UnlockTexture(overlay->hwdata->textureID);
overlay->hwfuncs->Unlock(_this, overlay);
} }


int int
SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect) SDL_DisplayYUVOverlay(SDL_Overlay * overlay, SDL_Rect * dstrect)
{ {
SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (SDL_RenderCopy(overlay->hwdata->textureID, NULL, dstrect,
SDL_Rect src, dst; SDL_TextureBlendMode_None,
int srcx, srcy, srcw, srch; SDL_TextureScaleMode_Fast) < 0) {
int dstx, dsty, dstw, dsth; return -1;

/* 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;
} }
/* Ugh, I can't wait for SDL_Rect to be int values */ SDL_RenderPresent();
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);
} }


void void
SDL_FreeYUVOverlay(SDL_Overlay * overlay) SDL_FreeYUVOverlay(SDL_Overlay * overlay)
{ {
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (overlay) { if (overlay) {
if (overlay->hwfuncs) { if (overlay->hwdata) {
overlay->hwfuncs->FreeHW(_this, overlay); if (overlay->hwdata->textureID) {
SDL_DestroyTexture(overlay->hwdata->textureID);
}
SDL_free(overlay->hwdata);
} }
SDL_free(overlay); SDL_free(overlay);
} }
} }
#endif


/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */

0 comments on commit 8e86df9

Please sign in to comment.