SDL-1.2.14
[sdl_omap.git] / src / video / SDL_yuv.c
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 }