src/video/SDL_yuv.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 21 Sep 2009 08:58:51 +0000
branchSDL-1.2
changeset 4214 4250beeb5ad1
parent 4159 a1b03ba2fcd0
child 6137 4720145f848b
permissions -rw-r--r--
Oh yeah, we have GLX support too.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 /* This is the implementation of the YUV video surface support */
    25 
    26 #include "SDL_video.h"
    27 #include "SDL_sysvideo.h"
    28 #include "SDL_yuvfuncs.h"
    29 #include "SDL_yuv_sw_c.h"
    30 
    31 
    32 SDL_Overlay *SDL_CreateYUVOverlay(int w, int h, Uint32 format,
    33                                   SDL_Surface *display)
    34 {
    35 	SDL_VideoDevice *video = current_video;
    36 	SDL_VideoDevice *this  = current_video;
    37 	const char *yuv_hwaccel;
    38 	SDL_Overlay *overlay;
    39 
    40 	if ( (display->flags & SDL_OPENGL) == SDL_OPENGL ) {
    41 		SDL_SetError("YUV overlays are not supported in OpenGL mode");
    42 		return NULL;
    43 	}
    44 
    45 	/* Display directly on video surface, if possible */
    46 	if ( SDL_getenv("SDL_VIDEO_YUV_DIRECT") ) {
    47 		if ( (display == SDL_PublicSurface) &&
    48 		     ((SDL_VideoSurface->format->BytesPerPixel == 2) ||
    49 		      (SDL_VideoSurface->format->BytesPerPixel == 4)) ) {
    50 			display = SDL_VideoSurface;
    51 		}
    52 	}
    53 	overlay = NULL;
    54         yuv_hwaccel = SDL_getenv("SDL_VIDEO_YUV_HWACCEL");
    55 	if ( ((display == SDL_VideoSurface) && video->CreateYUVOverlay) &&
    56 	     (!yuv_hwaccel || (SDL_atoi(yuv_hwaccel) > 0)) ) {
    57 		overlay = video->CreateYUVOverlay(this, w, h, format, display);
    58 	}
    59 	/* If hardware YUV overlay failed ... */
    60 	if ( overlay == NULL ) {
    61 		overlay = SDL_CreateYUV_SW(this, w, h, format, display);
    62 	}
    63 	return overlay;
    64 }
    65 
    66 int SDL_LockYUVOverlay(SDL_Overlay *overlay)
    67 {
    68 	if ( overlay == NULL ) {
    69 		SDL_SetError("Passed NULL overlay");
    70 		return -1;
    71 	}
    72 	return overlay->hwfuncs->Lock(current_video, overlay);
    73 }
    74 
    75 void SDL_UnlockYUVOverlay(SDL_Overlay *overlay)
    76 {
    77 	if ( overlay == NULL ) {
    78 		return;
    79 	}
    80 	overlay->hwfuncs->Unlock(current_video, overlay);
    81 }
    82 
    83 int SDL_DisplayYUVOverlay(SDL_Overlay *overlay, SDL_Rect *dstrect)
    84 {
    85 	SDL_Rect src, dst;
    86 	int srcx, srcy, srcw, srch;
    87 	int dstx, dsty, dstw, dsth;
    88 
    89 	if ( overlay == NULL || dstrect == NULL ) {
    90 		SDL_SetError("Passed NULL overlay or dstrect");
    91 		return -1;
    92 	}
    93 
    94 	/* Clip the rectangle to the screen area */
    95 	srcx = 0;
    96 	srcy = 0;
    97 	srcw = overlay->w;
    98 	srch = overlay->h;
    99 	dstx = dstrect->x;
   100 	dsty = dstrect->y;
   101 	dstw = dstrect->w;
   102 	dsth = dstrect->h;
   103 	if ( dstx < 0 ) {
   104 		srcw += (dstx * overlay->w) / dstrect->w;
   105 		dstw += dstx;
   106 		srcx -= (dstx * overlay->w) / dstrect->w;
   107 		dstx = 0;
   108 	}
   109 	if ( (dstx+dstw) > current_video->screen->w ) {
   110 		int extra = (dstx+dstw - current_video->screen->w);
   111 		srcw -= (extra * overlay->w) / dstrect->w;
   112 		dstw -= extra;
   113 	}
   114 	if ( dsty < 0 ) {
   115 		srch += (dsty * overlay->h) / dstrect->h;
   116 		dsth += dsty;
   117 		srcy -= (dsty * overlay->h) / dstrect->h;
   118 		dsty = 0;
   119 	}
   120 	if ( (dsty+dsth) > current_video->screen->h ) {
   121 		int extra = (dsty+dsth - current_video->screen->h);
   122 		srch -= (extra * overlay->h) / dstrect->h;
   123 		dsth -= extra;
   124 	}
   125 	if ( srcw <= 0 || srch <= 0 ||
   126 	     srch <= 0 || dsth <= 0 ) {
   127 		return 0;
   128 	}
   129 	/* Ugh, I can't wait for SDL_Rect to be int values */
   130 	src.x = srcx;
   131 	src.y = srcy;
   132 	src.w = srcw;
   133 	src.h = srch;
   134 	dst.x = dstx;
   135 	dst.y = dsty;
   136 	dst.w = dstw;
   137 	dst.h = dsth;
   138 	return overlay->hwfuncs->Display(current_video, overlay, &src, &dst);
   139 }
   140 
   141 void SDL_FreeYUVOverlay(SDL_Overlay *overlay)
   142 {
   143 	if ( overlay == NULL ) {
   144 		return;
   145 	}
   146 	if ( overlay->hwfuncs ) {
   147 		overlay->hwfuncs->FreeHW(current_video, overlay);
   148 	}
   149 	SDL_free(overlay);
   150 }