Mercurial > sdl-ios-xcode
comparison src/video/android/SDL_androidrender.c @ 4701:d40bb3165d2b
Added (partially implemented) android video backend and associated files needed to build
author | Paul Hunkin <paul@bieh.net> |
---|---|
date | Thu, 10 Jun 2010 18:54:23 +1200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4700:cf23d9b8e606 | 4701:d40bb3165d2b |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2010 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 #include "SDL_video.h" | |
25 #include "../SDL_sysvideo.h" | |
26 #include "../SDL_yuv_sw_c.h" | |
27 #include "../SDL_renderer_sw.h" | |
28 | |
29 | |
30 /* SDL surface based renderer implementation */ | |
31 | |
32 static SDL_Renderer *Android_CreateRenderer(SDL_Window * window, | |
33 Uint32 flags); | |
34 static int Android_RenderDrawPoints(SDL_Renderer * renderer, | |
35 const SDL_Point * points, int count); | |
36 static int Android_RenderDrawLines(SDL_Renderer * renderer, | |
37 const SDL_Point * points, int count); | |
38 static int Android_RenderDrawRects(SDL_Renderer * renderer, | |
39 const SDL_Rect ** rects, int count); | |
40 static int Android_RenderFillRects(SDL_Renderer * renderer, | |
41 const SDL_Rect ** rects, int count); | |
42 static int Android_RenderCopy(SDL_Renderer * renderer, | |
43 SDL_Texture * texture, | |
44 const SDL_Rect * srcrect, | |
45 const SDL_Rect * dstrect); | |
46 static int Android_RenderReadPixels(SDL_Renderer * renderer, | |
47 const SDL_Rect * rect, | |
48 Uint32 format, | |
49 void * pixels, int pitch); | |
50 static int Android_RenderWritePixels(SDL_Renderer * renderer, | |
51 const SDL_Rect * rect, | |
52 Uint32 format, | |
53 const void * pixels, int pitch); | |
54 static void Android_RenderPresent(SDL_Renderer * renderer); | |
55 static void Android_DestroyRenderer(SDL_Renderer * renderer); | |
56 | |
57 | |
58 SDL_RenderDriver Android_RenderDriver = { | |
59 Android_CreateRenderer, | |
60 { | |
61 "dummy", | |
62 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | | |
63 SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | | |
64 SDL_RENDERER_PRESENTDISCARD), | |
65 } | |
66 }; | |
67 | |
68 typedef struct | |
69 { | |
70 int current_screen; | |
71 SDL_Surface *screens[3]; | |
72 } Android_RenderData; | |
73 | |
74 SDL_Renderer * | |
75 Android_CreateRenderer(SDL_Window * window, Uint32 flags) | |
76 { | |
77 SDL_VideoDisplay *display = window->display; | |
78 SDL_DisplayMode *displayMode = &display->current_mode; | |
79 SDL_Renderer *renderer; | |
80 Android_RenderData *data; | |
81 int i, n; | |
82 int bpp; | |
83 Uint32 Rmask, Gmask, Bmask, Amask; | |
84 | |
85 if (!SDL_PixelFormatEnumToMasks | |
86 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
87 SDL_SetError("Unknown display format"); | |
88 return NULL; | |
89 } | |
90 | |
91 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); | |
92 if (!renderer) { | |
93 SDL_OutOfMemory(); | |
94 return NULL; | |
95 } | |
96 | |
97 data = (Android_RenderData *) SDL_malloc(sizeof(*data)); | |
98 if (!data) { | |
99 Android_DestroyRenderer(renderer); | |
100 SDL_OutOfMemory(); | |
101 return NULL; | |
102 } | |
103 SDL_zerop(data); | |
104 | |
105 renderer->RenderDrawPoints = Android_RenderDrawPoints; | |
106 renderer->RenderDrawLines = Android_RenderDrawLines; | |
107 renderer->RenderDrawRects = Android_RenderDrawRects; | |
108 renderer->RenderFillRects = Android_RenderFillRects; | |
109 renderer->RenderCopy = Android_RenderCopy; | |
110 renderer->RenderReadPixels = Android_RenderReadPixels; | |
111 renderer->RenderWritePixels = Android_RenderWritePixels; | |
112 renderer->RenderPresent = Android_RenderPresent; | |
113 renderer->DestroyRenderer = Android_DestroyRenderer; | |
114 renderer->info.name = Android_RenderDriver.info.name; | |
115 renderer->info.flags = 0; | |
116 renderer->window = window; | |
117 renderer->driverdata = data; | |
118 Setup_SoftwareRenderer(renderer); | |
119 | |
120 if (flags & SDL_RENDERER_PRESENTFLIP2) { | |
121 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2; | |
122 n = 2; | |
123 } else if (flags & SDL_RENDERER_PRESENTFLIP3) { | |
124 renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3; | |
125 n = 3; | |
126 } else { | |
127 renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; | |
128 n = 1; | |
129 } | |
130 for (i = 0; i < n; ++i) { | |
131 data->screens[i] = | |
132 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask, | |
133 Bmask, Amask); | |
134 if (!data->screens[i]) { | |
135 Android_DestroyRenderer(renderer); | |
136 return NULL; | |
137 } | |
138 SDL_SetSurfacePalette(data->screens[i], display->palette); | |
139 } | |
140 data->current_screen = 0; | |
141 | |
142 return renderer; | |
143 } | |
144 | |
145 static int | |
146 Android_RenderDrawPoints(SDL_Renderer * renderer, | |
147 const SDL_Point * points, int count) | |
148 { | |
149 Android_RenderData *data = | |
150 (Android_RenderData *) renderer->driverdata; | |
151 SDL_Surface *target = data->screens[data->current_screen]; | |
152 | |
153 if (renderer->blendMode == SDL_BLENDMODE_NONE || | |
154 renderer->blendMode == SDL_BLENDMODE_MASK) { | |
155 Uint32 color = SDL_MapRGBA(target->format, | |
156 renderer->r, renderer->g, renderer->b, | |
157 renderer->a); | |
158 | |
159 return SDL_DrawPoints(target, points, count, color); | |
160 } else { | |
161 return SDL_BlendPoints(target, points, count, renderer->blendMode, | |
162 renderer->r, renderer->g, renderer->b, | |
163 renderer->a); | |
164 } | |
165 } | |
166 | |
167 static int | |
168 Android_RenderDrawLines(SDL_Renderer * renderer, | |
169 const SDL_Point * points, int count) | |
170 { | |
171 Android_RenderData *data = | |
172 (Android_RenderData *) renderer->driverdata; | |
173 SDL_Surface *target = data->screens[data->current_screen]; | |
174 | |
175 if (renderer->blendMode == SDL_BLENDMODE_NONE || | |
176 renderer->blendMode == SDL_BLENDMODE_MASK) { | |
177 Uint32 color = SDL_MapRGBA(target->format, | |
178 renderer->r, renderer->g, renderer->b, | |
179 renderer->a); | |
180 | |
181 return SDL_DrawLines(target, points, count, color); | |
182 } else { | |
183 return SDL_BlendLines(target, points, count, renderer->blendMode, | |
184 renderer->r, renderer->g, renderer->b, | |
185 renderer->a); | |
186 } | |
187 } | |
188 | |
189 static int | |
190 Android_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects, | |
191 int count) | |
192 { | |
193 Android_RenderData *data = | |
194 (Android_RenderData *) renderer->driverdata; | |
195 SDL_Surface *target = data->screens[data->current_screen]; | |
196 | |
197 if (renderer->blendMode == SDL_BLENDMODE_NONE || | |
198 renderer->blendMode == SDL_BLENDMODE_MASK) { | |
199 Uint32 color = SDL_MapRGBA(target->format, | |
200 renderer->r, renderer->g, renderer->b, | |
201 renderer->a); | |
202 | |
203 return SDL_DrawRects(target, rects, count, color); | |
204 } else { | |
205 return SDL_BlendRects(target, rects, count, | |
206 renderer->blendMode, | |
207 renderer->r, renderer->g, renderer->b, | |
208 renderer->a); | |
209 } | |
210 } | |
211 | |
212 static int | |
213 Android_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, | |
214 int count) | |
215 { | |
216 Android_RenderData *data = | |
217 (Android_RenderData *) renderer->driverdata; | |
218 SDL_Surface *target = data->screens[data->current_screen]; | |
219 | |
220 if (renderer->blendMode == SDL_BLENDMODE_NONE || | |
221 renderer->blendMode == SDL_BLENDMODE_MASK) { | |
222 Uint32 color = SDL_MapRGBA(target->format, | |
223 renderer->r, renderer->g, renderer->b, | |
224 renderer->a); | |
225 | |
226 return SDL_FillRects(target, rects, count, color); | |
227 } else { | |
228 return SDL_BlendFillRects(target, rects, count, | |
229 renderer->blendMode, | |
230 renderer->r, renderer->g, renderer->b, | |
231 renderer->a); | |
232 } | |
233 } | |
234 | |
235 static int | |
236 Android_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
237 const SDL_Rect * srcrect, const SDL_Rect * dstrect) | |
238 { | |
239 Android_RenderData *data = | |
240 (Android_RenderData *) renderer->driverdata; | |
241 SDL_Window *window = renderer->window; | |
242 SDL_VideoDisplay *display = window->display; | |
243 | |
244 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
245 SDL_Surface *target = data->screens[data->current_screen]; | |
246 void *pixels = | |
247 (Uint8 *) target->pixels + dstrect->y * target->pitch + | |
248 dstrect->x * target->format->BytesPerPixel; | |
249 return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, | |
250 srcrect, display->current_mode.format, | |
251 dstrect->w, dstrect->h, pixels, | |
252 target->pitch); | |
253 } else { | |
254 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
255 SDL_Surface *target = data->screens[data->current_screen]; | |
256 SDL_Rect real_srcrect = *srcrect; | |
257 SDL_Rect real_dstrect = *dstrect; | |
258 | |
259 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect); | |
260 } | |
261 } | |
262 | |
263 static int | |
264 Android_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, | |
265 Uint32 format, void * pixels, int pitch) | |
266 { | |
267 Android_RenderData *data = | |
268 (Android_RenderData *) renderer->driverdata; | |
269 SDL_Window *window = renderer->window; | |
270 SDL_VideoDisplay *display = window->display; | |
271 SDL_Surface *screen = data->screens[data->current_screen]; | |
272 Uint32 screen_format = display->current_mode.format; | |
273 Uint8 *screen_pixels = (Uint8 *) screen->pixels + | |
274 rect->y * screen->pitch + | |
275 rect->x * screen->format->BytesPerPixel; | |
276 int screen_pitch = screen->pitch; | |
277 | |
278 return SDL_ConvertPixels(rect->w, rect->h, | |
279 screen_format, screen_pixels, screen_pitch, | |
280 format, pixels, pitch); | |
281 } | |
282 | |
283 static int | |
284 Android_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, | |
285 Uint32 format, const void * pixels, int pitch) | |
286 { | |
287 Android_RenderData *data = | |
288 (Android_RenderData *) renderer->driverdata; | |
289 SDL_Window *window = renderer->window; | |
290 SDL_VideoDisplay *display = window->display; | |
291 SDL_Surface *screen = data->screens[data->current_screen]; | |
292 Uint32 screen_format = display->current_mode.format; | |
293 Uint8 *screen_pixels = (Uint8 *) screen->pixels + | |
294 rect->y * screen->pitch + | |
295 rect->x * screen->format->BytesPerPixel; | |
296 int screen_pitch = screen->pitch; | |
297 | |
298 return SDL_ConvertPixels(rect->w, rect->h, | |
299 format, pixels, pitch, | |
300 screen_format, screen_pixels, screen_pitch); | |
301 } | |
302 | |
303 static void | |
304 Android_RenderPresent(SDL_Renderer * renderer) | |
305 { | |
306 static int frame_number; | |
307 Android_RenderData *data = | |
308 (Android_RenderData *) renderer->driverdata; | |
309 | |
310 /* Send the data to the display */ | |
311 if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) { | |
312 char file[128]; | |
313 SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", | |
314 renderer->window->id, ++frame_number); | |
315 SDL_SaveBMP(data->screens[data->current_screen], file); | |
316 } | |
317 | |
318 /* Update the flipping chain, if any */ | |
319 if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) { | |
320 data->current_screen = (data->current_screen + 1) % 2; | |
321 } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) { | |
322 data->current_screen = (data->current_screen + 1) % 3; | |
323 } | |
324 } | |
325 | |
326 static void | |
327 Android_DestroyRenderer(SDL_Renderer * renderer) | |
328 { | |
329 Android_RenderData *data = | |
330 (Android_RenderData *) renderer->driverdata; | |
331 int i; | |
332 | |
333 if (data) { | |
334 for (i = 0; i < SDL_arraysize(data->screens); ++i) { | |
335 if (data->screens[i]) { | |
336 SDL_FreeSurface(data->screens[i]); | |
337 } | |
338 } | |
339 SDL_free(data); | |
340 } | |
341 SDL_free(renderer); | |
342 } | |
343 | |
344 /* vi: set ts=4 sw=4 expandtab: */ |