1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 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
32SDL_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
66int 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
75void SDL_UnlockYUVOverlay(SDL_Overlay *overlay)
76{
77	if ( overlay == NULL ) {
78		return;
79	}
80	overlay->hwfuncs->Unlock(current_video, overlay);
81}
82
83int 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
141void 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}
151