Mercurial > sdl-ios-xcode
annotate src/video/windx5/SDL_dx5yuv.c @ 1240:3b8a43c428bb
From Bug #36:
There are a couple of issues with the selection of Altivec alpha-blitting
routines in CalculateAlphaBlit() in src/video/SDL_Blit_A.c.
1) There's no check for the presence of Altivec when checking if the
Blit32to565PixelAlphaAltivec() routine can be selected.
2) Altivec cannot be used in video memory, and there's no check if the
destination surface is a hardware surface. (Alpha-blitting to a hardware
surface with GPU support is a bad idea, but somebody's bound to do it anyway.)
Patch to fix these attached.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sun, 08 Jan 2006 21:18:15 +0000 |
parents | e06ec825242d |
children | c9b51268668f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
33
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* This is the DirectDraw implementation of YUV video overlays */ | |
29 | |
30 #include <stdlib.h> | |
31 #include <string.h> | |
32 | |
33 #include "SDL_error.h" | |
34 #include "SDL_video.h" | |
35 #include "SDL_dx5yuv_c.h" | |
36 #include "SDL_yuvfuncs.h" | |
37 | |
811
e06ec825242d
Don't use hardware overlay by default (seems much faster this way)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
38 //#define USE_DIRECTX_OVERLAY |
0 | 39 |
40 /* The functions used to manipulate software video overlays */ | |
41 static struct private_yuvhwfuncs dx5_yuvfuncs = { | |
42 DX5_LockYUVOverlay, | |
43 DX5_UnlockYUVOverlay, | |
44 DX5_DisplayYUVOverlay, | |
45 DX5_FreeYUVOverlay | |
46 }; | |
47 | |
48 struct private_yuvhwdata { | |
49 LPDIRECTDRAWSURFACE3 surface; | |
50 | |
51 /* These are just so we don't have to allocate them separately */ | |
52 Uint16 pitches[3]; | |
53 Uint8 *planes[3]; | |
54 }; | |
55 | |
56 | |
57 static LPDIRECTDRAWSURFACE3 CreateYUVSurface(_THIS, | |
58 int width, int height, Uint32 format) | |
59 { | |
60 HRESULT result; | |
61 LPDIRECTDRAWSURFACE dd_surface1; | |
62 LPDIRECTDRAWSURFACE3 dd_surface3; | |
63 DDSURFACEDESC ddsd; | |
64 | |
65 /* Set up the surface description */ | |
66 memset(&ddsd, 0, sizeof(ddsd)); | |
67 ddsd.dwSize = sizeof(ddsd); | |
68 ddsd.dwFlags = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); | |
69 ddsd.dwWidth = width; | |
70 ddsd.dwHeight= height; | |
71 #ifdef USE_DIRECTX_OVERLAY | |
72 ddsd.ddsCaps.dwCaps = (DDSCAPS_OVERLAY|DDSCAPS_VIDEOMEMORY); | |
73 #else | |
74 ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY); | |
75 #endif | |
76 ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); | |
77 ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; | |
78 ddsd.ddpfPixelFormat.dwFourCC = format; | |
79 | |
80 /* Create the DirectDraw video surface */ | |
81 result = IDirectDraw2_CreateSurface(ddraw2, &ddsd, &dd_surface1, NULL); | |
82 if ( result != DD_OK ) { | |
83 SetDDerror("DirectDraw2::CreateSurface", result); | |
84 return(NULL); | |
85 } | |
86 result = IDirectDrawSurface_QueryInterface(dd_surface1, | |
87 &IID_IDirectDrawSurface3, (LPVOID *)&dd_surface3); | |
88 IDirectDrawSurface_Release(dd_surface1); | |
89 if ( result != DD_OK ) { | |
90 SetDDerror("DirectDrawSurface::QueryInterface", result); | |
91 return(NULL); | |
92 } | |
93 | |
94 /* Make sure the surface format was set properly */ | |
95 memset(&ddsd, 0, sizeof(ddsd)); | |
96 ddsd.dwSize = sizeof(ddsd); | |
97 result = IDirectDrawSurface3_Lock(dd_surface3, NULL, | |
98 &ddsd, DDLOCK_NOSYSLOCK, NULL); | |
99 if ( result != DD_OK ) { | |
100 SetDDerror("DirectDrawSurface3::Lock", result); | |
101 IDirectDrawSurface_Release(dd_surface3); | |
102 return(NULL); | |
103 } | |
104 IDirectDrawSurface3_Unlock(dd_surface3, NULL); | |
105 | |
106 if ( !(ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC) || | |
107 (ddsd.ddpfPixelFormat.dwFourCC != format) ) { | |
108 SDL_SetError("DDraw didn't use requested FourCC format"); | |
109 IDirectDrawSurface_Release(dd_surface3); | |
110 return(NULL); | |
111 } | |
112 | |
113 /* We're ready to go! */ | |
114 return(dd_surface3); | |
115 } | |
116 | |
117 #ifdef DEBUG_YUV | |
118 static char *PrintFOURCC(Uint32 code) | |
119 { | |
120 static char buf[5]; | |
121 | |
122 buf[3] = code >> 24; | |
123 buf[2] = (code >> 16) & 0xFF; | |
124 buf[1] = (code >> 8) & 0xFF; | |
125 buf[0] = (code & 0xFF); | |
126 return(buf); | |
127 } | |
128 #endif | |
129 | |
130 SDL_Overlay *DX5_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) | |
131 { | |
132 SDL_Overlay *overlay; | |
133 struct private_yuvhwdata *hwdata; | |
134 | |
135 #ifdef DEBUG_YUV | |
136 DWORD numcodes; | |
137 DWORD *codes; | |
138 | |
139 printf("FOURCC format requested: 0x%x\n", PrintFOURCC(format)); | |
140 IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, NULL); | |
141 if ( numcodes ) { | |
142 DWORD i; | |
143 codes = malloc(numcodes*sizeof(*codes)); | |
144 if ( codes ) { | |
145 IDirectDraw2_GetFourCCCodes(ddraw2, &numcodes, codes); | |
146 for ( i=0; i<numcodes; ++i ) { | |
147 fprintf(stderr, "Code %d: 0x%x\n", i, PrintFOURCC(codes[i])); | |
148 } | |
149 free(codes); | |
150 } | |
151 } else { | |
152 fprintf(stderr, "No FOURCC codes supported\n"); | |
153 } | |
154 #endif | |
155 | |
156 /* Create the overlay structure */ | |
157 overlay = (SDL_Overlay *)malloc(sizeof *overlay); | |
158 if ( overlay == NULL ) { | |
159 SDL_OutOfMemory(); | |
160 return(NULL); | |
161 } | |
162 memset(overlay, 0, (sizeof *overlay)); | |
163 | |
164 /* Fill in the basic members */ | |
165 overlay->format = format; | |
166 overlay->w = width; | |
167 overlay->h = height; | |
168 | |
169 /* Set up the YUV surface function structure */ | |
170 overlay->hwfuncs = &dx5_yuvfuncs; | |
171 | |
172 /* Create the pixel data and lookup tables */ | |
173 hwdata = (struct private_yuvhwdata *)malloc(sizeof *hwdata); | |
174 overlay->hwdata = hwdata; | |
175 if ( hwdata == NULL ) { | |
176 SDL_OutOfMemory(); | |
177 SDL_FreeYUVOverlay(overlay); | |
178 return(NULL); | |
179 } | |
180 hwdata->surface = CreateYUVSurface(this, width, height, format); | |
181 if ( hwdata->surface == NULL ) { | |
182 SDL_FreeYUVOverlay(overlay); | |
183 return(NULL); | |
184 } | |
185 overlay->hw_overlay = 1; | |
186 | |
187 /* Set up the plane pointers */ | |
188 overlay->pitches = hwdata->pitches; | |
189 overlay->pixels = hwdata->planes; | |
190 switch (format) { | |
191 case SDL_YV12_OVERLAY: | |
192 case SDL_IYUV_OVERLAY: | |
193 overlay->planes = 3; | |
33
81a7158fa836
Silly bug fix from Billy Biggs
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
194 break; |
0 | 195 default: |
196 overlay->planes = 1; | |
197 break; | |
198 } | |
199 | |
200 /* We're all done.. */ | |
201 return(overlay); | |
202 } | |
203 | |
204 int DX5_LockYUVOverlay(_THIS, SDL_Overlay *overlay) | |
205 { | |
206 HRESULT result; | |
207 LPDIRECTDRAWSURFACE3 surface; | |
208 DDSURFACEDESC ddsd; | |
209 | |
210 surface = overlay->hwdata->surface; | |
211 memset(&ddsd, 0, sizeof(ddsd)); | |
212 ddsd.dwSize = sizeof(ddsd); | |
213 result = IDirectDrawSurface3_Lock(surface, NULL, | |
214 &ddsd, DDLOCK_NOSYSLOCK, NULL); | |
215 if ( result == DDERR_SURFACELOST ) { | |
216 result = IDirectDrawSurface3_Restore(surface); | |
217 result = IDirectDrawSurface3_Lock(surface, NULL, &ddsd, | |
218 (DDLOCK_NOSYSLOCK|DDLOCK_WAIT), NULL); | |
219 } | |
220 if ( result != DD_OK ) { | |
221 SetDDerror("DirectDrawSurface3::Lock", result); | |
222 return(-1); | |
223 } | |
224 | |
225 /* Find the pitch and offset values for the overlay */ | |
226 #if defined(NONAMELESSUNION) | |
227 overlay->pitches[0] = (Uint16)ddsd.u1.lPitch; | |
228 #else | |
229 overlay->pitches[0] = (Uint16)ddsd.lPitch; | |
230 #endif | |
231 overlay->pixels[0] = (Uint8 *)ddsd.lpSurface; | |
232 switch (overlay->format) { | |
233 case SDL_YV12_OVERLAY: | |
234 case SDL_IYUV_OVERLAY: | |
235 /* Add the two extra planes */ | |
236 overlay->pitches[1] = overlay->pitches[0] / 2; | |
237 overlay->pitches[2] = overlay->pitches[0] / 2; | |
238 overlay->pixels[1] = overlay->pixels[0] + | |
239 overlay->pitches[0] * overlay->h; | |
240 overlay->pixels[2] = overlay->pixels[1] + | |
241 overlay->pitches[1] * overlay->h / 2; | |
242 break; | |
243 default: | |
244 /* Only one plane, no worries */ | |
245 break; | |
246 } | |
247 return(0); | |
248 } | |
249 | |
250 void DX5_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) | |
251 { | |
252 LPDIRECTDRAWSURFACE3 surface; | |
253 | |
254 surface = overlay->hwdata->surface; | |
255 IDirectDrawSurface3_Unlock(surface, NULL); | |
256 } | |
257 | |
258 int DX5_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) | |
259 { | |
260 HRESULT result; | |
261 LPDIRECTDRAWSURFACE3 surface; | |
262 RECT src, dst; | |
263 | |
264 surface = overlay->hwdata->surface; | |
265 src.top = 0; | |
266 src.bottom = overlay->h; | |
267 src.left = 0; | |
268 src.right = overlay->w; | |
269 dst.top = SDL_bounds.top+dstrect->y; | |
270 dst.left = SDL_bounds.left+dstrect->x; | |
271 dst.bottom = dst.top+dstrect->h; | |
272 dst.right = dst.left+dstrect->w; | |
273 #ifdef USE_DIRECTX_OVERLAY | |
274 result = IDirectDrawSurface3_UpdateOverlay(surface, &src, | |
275 SDL_primary, &dst, DDOVER_SHOW, NULL); | |
276 if ( result != DD_OK ) { | |
277 SetDDerror("DirectDrawSurface3::UpdateOverlay", result); | |
278 return(-1); | |
279 } | |
280 #else | |
281 result = IDirectDrawSurface3_Blt(SDL_primary, &dst, surface, &src, | |
282 DDBLT_WAIT, NULL); | |
283 if ( result != DD_OK ) { | |
284 SetDDerror("DirectDrawSurface3::Blt", result); | |
285 return(-1); | |
286 } | |
287 #endif | |
288 return(0); | |
289 } | |
290 | |
291 void DX5_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) | |
292 { | |
293 struct private_yuvhwdata *hwdata; | |
294 | |
295 hwdata = overlay->hwdata; | |
296 if ( hwdata ) { | |
297 if ( hwdata->surface ) { | |
298 IDirectDrawSurface_Release(hwdata->surface); | |
299 } | |
300 free(hwdata); | |
301 } | |
302 } | |
303 |