e14743d1 |
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 | } |