src/video/SDL_yuv.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 17 Apr 2006 06:47:23 +0000
changeset 1643 51038e80ae59
parent 1402 d910939febfa
child 1662 782fd950bd46
child 4076 9a7c62bbc8b3
permissions -rw-r--r--
More general fix for bug #189

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