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 
SDL_CreateYUVOverlay(int w,int h,Uint32 format,SDL_Surface * display)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 
SDL_LockYUVOverlay(SDL_Overlay * overlay)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 
SDL_UnlockYUVOverlay(SDL_Overlay * overlay)75 void SDL_UnlockYUVOverlay(SDL_Overlay *overlay)
76 {
77  if ( overlay == NULL ) {
78    return;
79  }
80  overlay->hwfuncs->Unlock(current_video, overlay);
81 }
82 
SDL_DisplayYUVOverlay(SDL_Overlay * overlay,SDL_Rect * dstrect)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 
SDL_FreeYUVOverlay(SDL_Overlay * overlay)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 }
151