Mercurial > sdl-ios-xcode
comparison src/video/SDL_renderer_sw.c @ 1676:e136f3ffdc1b SDL-1.3
Adding software renderer implementation
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 12 Jun 2006 09:10:06 +0000 |
parents | |
children | 90bf530ced8e |
comparison
equal
deleted
inserted
replaced
1675:d33dcfc3fde7 | 1676:e136f3ffdc1b |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2006 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 | |
27 | |
28 /* SDL surface based renderer implementation */ | |
29 | |
30 static SDL_Renderer *SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags); | |
31 static int SDL_SW_CreateTexture(SDL_Renderer * renderer, | |
32 SDL_Texture * texture); | |
33 static int SDL_SW_UpdateTexture(SDL_Renderer * renderer, | |
34 SDL_Texture * texture, SDL_Rect * rect, | |
35 const void *pixels, int pitch); | |
36 static int SDL_SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
37 SDL_Rect * rect, int markDirty, void **pixels, | |
38 int *pitch); | |
39 static void SDL_SW_UnlockTexture(SDL_Renderer * renderer, | |
40 SDL_Texture * texture); | |
41 static void SDL_SW_DirtyTexture(SDL_Renderer * renderer, | |
42 SDL_Texture * texture, int numrects, | |
43 SDL_Rect * rects); | |
44 static void SDL_SW_SelectRenderTexture(SDL_Renderer * renderer, | |
45 SDL_Texture * texture); | |
46 static void SDL_SW_RenderFill(SDL_Renderer * renderer, SDL_Rect * rect, | |
47 Uint32 color); | |
48 static int SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
49 SDL_Rect * srcrect, SDL_Rect * dstrect, | |
50 int blendMode, int scaleMode); | |
51 static int SDL_SW_RenderReadPixels(SDL_Renderer * renderer, SDL_Rect * rect, | |
52 void *pixels, int pitch); | |
53 static int SDL_SW_RenderWritePixels(SDL_Renderer * renderer, SDL_Rect * rect, | |
54 const void *pixels, int pitch); | |
55 static void SDL_SW_RenderPresent(SDL_Renderer * renderer); | |
56 static void SDL_SW_DestroyTexture(SDL_Renderer * renderer, | |
57 SDL_Texture * texture); | |
58 static void SDL_SW_DestroyRenderer(SDL_Renderer * renderer); | |
59 | |
60 | |
61 SDL_RenderDriver SDL_SW_RenderDriver = { | |
62 SDL_SW_CreateRenderer, | |
63 { | |
64 "software", | |
65 (SDL_Renderer_PresentDiscard | | |
66 SDL_Renderer_PresentCopy | | |
67 SDL_Renderer_PresentFlip2 | | |
68 SDL_Renderer_PresentFlip3 | SDL_Renderer_RenderTarget), | |
69 (SDL_TextureBlendMode_None | | |
70 SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend), | |
71 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast), | |
72 11, | |
73 { | |
74 SDL_PixelFormat_Index8, | |
75 SDL_PixelFormat_RGB555, | |
76 SDL_PixelFormat_RGB565, | |
77 SDL_PixelFormat_RGB888, | |
78 SDL_PixelFormat_BGR888, | |
79 SDL_PixelFormat_ARGB8888, | |
80 SDL_PixelFormat_RGBA8888, | |
81 SDL_PixelFormat_ABGR8888, | |
82 SDL_PixelFormat_BGRA8888, | |
83 SDL_PixelFormat_YUY2, | |
84 SDL_PixelFormat_UYVY}, | |
85 32768, | |
86 32768} | |
87 }; | |
88 | |
89 typedef struct | |
90 { | |
91 int current_screen; | |
92 SDL_Surface *screens[3]; | |
93 SDL_Surface *target; | |
94 SDL_Renderer *renderer; | |
95 } SDL_SW_RenderData; | |
96 | |
97 SDL_Renderer * | |
98 SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) | |
99 { | |
100 SDL_DisplayMode *displayMode = &window->display->current_mode; | |
101 SDL_Renderer *renderer; | |
102 SDL_SW_RenderData *data; | |
103 int i, n; | |
104 int bpp; | |
105 Uint32 Rmask, Gmask, Bmask, Amask; | |
106 | |
107 if (!SDL_PixelFormatEnumToMasks | |
108 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
109 SDL_SetError("Unknown display format"); | |
110 return NULL; | |
111 } | |
112 | |
113 renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer)); | |
114 if (!renderer) { | |
115 SDL_OutOfMemory(); | |
116 return NULL; | |
117 } | |
118 SDL_zerop(renderer); | |
119 | |
120 data = (SDL_SW_RenderData *) SDL_malloc(sizeof(*data)); | |
121 if (!data) { | |
122 SDL_SW_DestroyRenderer(renderer); | |
123 SDL_OutOfMemory(); | |
124 return NULL; | |
125 } | |
126 SDL_zerop(data); | |
127 | |
128 renderer->CreateTexture = SDL_SW_CreateTexture; | |
129 renderer->UpdateTexture = SDL_SW_UpdateTexture; | |
130 renderer->LockTexture = SDL_SW_LockTexture; | |
131 renderer->UnlockTexture = SDL_SW_UnlockTexture; | |
132 renderer->DirtyTexture = SDL_SW_DirtyTexture; | |
133 renderer->SelectRenderTexture = SDL_SW_SelectRenderTexture; | |
134 renderer->RenderFill = SDL_SW_RenderFill; | |
135 renderer->RenderCopy = SDL_SW_RenderCopy; | |
136 renderer->RenderReadPixels = SDL_SW_RenderReadPixels; | |
137 renderer->RenderWritePixels = SDL_SW_RenderWritePixels; | |
138 renderer->RenderPresent = SDL_SW_RenderPresent; | |
139 renderer->DestroyTexture = SDL_SW_DestroyTexture; | |
140 renderer->DestroyRenderer = SDL_SW_DestroyRenderer; | |
141 renderer->info = SDL_SW_RenderDriver.info; | |
142 renderer->window = window; | |
143 renderer->driverdata = data; | |
144 | |
145 renderer->info.flags = SDL_Renderer_RenderTarget; | |
146 | |
147 if (flags & SDL_Renderer_PresentFlip2) { | |
148 renderer->info.flags |= SDL_Renderer_PresentFlip2; | |
149 n = 2; | |
150 } else if (flags & SDL_Renderer_PresentFlip3) { | |
151 renderer->info.flags |= SDL_Renderer_PresentFlip3; | |
152 n = 3; | |
153 } else { | |
154 renderer->info.flags |= SDL_Renderer_PresentCopy; | |
155 n = 1; | |
156 } | |
157 for (i = 0; i < n; ++i) { | |
158 data->screens[i] = | |
159 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask, | |
160 Bmask, Amask); | |
161 if (!data->screens[i]) { | |
162 SDL_SW_DestroyRenderer(renderer); | |
163 return NULL; | |
164 } | |
165 } | |
166 data->current_screen = 0; | |
167 data->target = data->screens[0]; | |
168 | |
169 /* Find a render driver that we can use to display data */ | |
170 for (i = 0; i < window->display->num_render_drivers; ++i) { | |
171 SDL_RenderDriver *driver = &window->display->render_drivers[i]; | |
172 if (driver->info.name != SDL_SW_RenderDriver.info.name) { | |
173 data->renderer = | |
174 driver->CreateRenderer(window, SDL_Renderer_PresentDiscard); | |
175 if (data->renderer) { | |
176 break; | |
177 } | |
178 } | |
179 } | |
180 if (i == window->display->num_render_drivers) { | |
181 SDL_SW_DestroyRenderer(renderer); | |
182 SDL_SetError("Couldn't find display render driver"); | |
183 return NULL; | |
184 } | |
185 return renderer; | |
186 } | |
187 | |
188 int | |
189 SDL_SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
190 { | |
191 SDL_Surface *surface; | |
192 int bpp; | |
193 Uint32 Rmask, Gmask, Bmask, Amask; | |
194 | |
195 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
196 /* FIXME: implement this */ | |
197 return -1; | |
198 } | |
199 | |
200 if (!SDL_PixelFormatEnumToMasks | |
201 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
202 SDL_SetError("Unknown texture format"); | |
203 return -1; | |
204 } | |
205 | |
206 surface = | |
207 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, | |
208 Bmask, Amask); | |
209 if (!surface) { | |
210 return -1; | |
211 } | |
212 | |
213 texture->driverdata = surface; | |
214 return 0; | |
215 } | |
216 | |
217 int | |
218 SDL_SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
219 SDL_Rect * rect, const void *pixels, int pitch) | |
220 { | |
221 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
222 Uint8 *src, *dst; | |
223 int row; | |
224 size_t length; | |
225 | |
226 src = (Uint8 *) pixels; | |
227 dst = | |
228 (Uint8 *) surface->pixels + rect->y * surface->pitch + | |
229 rect->x * surface->format->BytesPerPixel; | |
230 length = rect->w * surface->format->BytesPerPixel; | |
231 for (row = 0; row < rect->h; ++row) { | |
232 SDL_memcpy(dst, src, length); | |
233 src += pitch; | |
234 dst += surface->pitch; | |
235 } | |
236 return 0; | |
237 } | |
238 | |
239 int | |
240 SDL_SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
241 SDL_Rect * rect, int markDirty, void **pixels, int *pitch) | |
242 { | |
243 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
244 | |
245 *pixels = | |
246 (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch + | |
247 rect->x * surface->format->BytesPerPixel); | |
248 *pitch = surface->pitch; | |
249 return 0; | |
250 } | |
251 | |
252 void | |
253 SDL_SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
254 { | |
255 } | |
256 | |
257 void | |
258 SDL_SW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
259 int numrects, SDL_Rect * rects) | |
260 { | |
261 } | |
262 | |
263 void | |
264 SDL_SW_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
265 { | |
266 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
267 data->target = (SDL_Surface *) texture->driverdata; | |
268 } | |
269 | |
270 void | |
271 SDL_SW_RenderFill(SDL_Renderer * renderer, SDL_Rect * rect, Uint32 color) | |
272 { | |
273 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
274 Uint8 r, g, b, a; | |
275 | |
276 a = (Uint8) ((color >> 24) & 0xFF); | |
277 r = (Uint8) ((color >> 16) & 0xFF); | |
278 g = (Uint8) ((color >> 8) & 0xFF); | |
279 b = (Uint8) (color & 0xFF); | |
280 color = SDL_MapRGBA(data->target->format, r, g, b, a); | |
281 | |
282 SDL_FillRect(data->target, rect, color); | |
283 } | |
284 | |
285 int | |
286 SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
287 SDL_Rect * srcrect, SDL_Rect * dstrect, int blendMode, | |
288 int scaleMode) | |
289 { | |
290 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
291 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
292 | |
293 if (blendMode & (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) { | |
294 SDL_SetAlpha(surface, SDL_SRCALPHA, 0); | |
295 } else { | |
296 SDL_SetAlpha(surface, 0, 0); | |
297 } | |
298 if (scaleMode != SDL_TextureScaleMode_None && | |
299 (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) { | |
300 return SDL_SoftStretch(surface, srcrect, data->target, dstrect); | |
301 } else { | |
302 return SDL_LowerBlit(surface, srcrect, data->target, dstrect); | |
303 } | |
304 } | |
305 | |
306 int | |
307 SDL_SW_RenderReadPixels(SDL_Renderer * renderer, SDL_Rect * rect, | |
308 void *pixels, int pitch) | |
309 { | |
310 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
311 SDL_Surface *surface = data->target; | |
312 Uint8 *src, *dst; | |
313 int row; | |
314 size_t length; | |
315 | |
316 src = | |
317 (Uint8 *) surface->pixels + rect->y * surface->pitch + | |
318 rect->x * surface->format->BytesPerPixel; | |
319 dst = (Uint8 *) pixels; | |
320 length = rect->w * surface->format->BytesPerPixel; | |
321 for (row = 0; row < rect->h; ++row) { | |
322 SDL_memcpy(dst, src, length); | |
323 src += surface->pitch; | |
324 dst += pitch; | |
325 } | |
326 return 0; | |
327 } | |
328 | |
329 int | |
330 SDL_SW_RenderWritePixels(SDL_Renderer * renderer, SDL_Rect * rect, | |
331 const void *pixels, int pitch) | |
332 { | |
333 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
334 SDL_Surface *surface = data->target; | |
335 Uint8 *src, *dst; | |
336 int row; | |
337 size_t length; | |
338 | |
339 src = (Uint8 *) pixels; | |
340 dst = | |
341 (Uint8 *) surface->pixels + rect->y * surface->pitch + | |
342 rect->x * surface->format->BytesPerPixel; | |
343 length = rect->w * surface->format->BytesPerPixel; | |
344 for (row = 0; row < rect->h; ++row) { | |
345 SDL_memcpy(dst, src, length); | |
346 src += pitch; | |
347 dst += surface->pitch; | |
348 } | |
349 return 0; | |
350 } | |
351 | |
352 void | |
353 SDL_SW_RenderPresent(SDL_Renderer * renderer) | |
354 { | |
355 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
356 SDL_Surface *surface = data->screens[data->current_screen]; | |
357 SDL_Rect rect; | |
358 int new_screen; | |
359 | |
360 /* Send the data to the display */ | |
361 /* FIXME: implement dirty rect updates */ | |
362 rect.x = 0; | |
363 rect.y = 0; | |
364 rect.w = surface->w; | |
365 rect.h = surface->h; | |
366 data->renderer->RenderWritePixels(data->renderer, &rect, surface->pixels, | |
367 surface->pitch); | |
368 data->renderer->RenderPresent(data->renderer); | |
369 | |
370 /* Update the flipping chain, if any */ | |
371 if (renderer->info.flags & SDL_Renderer_PresentFlip2) { | |
372 new_screen = (data->current_screen + 1) % 2; | |
373 } else if (renderer->info.flags & SDL_Renderer_PresentFlip3) { | |
374 new_screen = (data->current_screen + 1) % 3; | |
375 } else { | |
376 new_screen = 0; | |
377 } | |
378 if (data->target == data->screens[data->current_screen]) { | |
379 data->target = data->screens[new_screen]; | |
380 } | |
381 data->current_screen = new_screen; | |
382 } | |
383 | |
384 void | |
385 SDL_SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
386 { | |
387 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
388 | |
389 SDL_FreeSurface(surface); | |
390 } | |
391 | |
392 void | |
393 SDL_SW_DestroyRenderer(SDL_Renderer * renderer) | |
394 { | |
395 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
396 int i; | |
397 | |
398 if (data) { | |
399 for (i = 0; i < SDL_arraysize(data->screens); ++i) { | |
400 if (data->screens[i]) { | |
401 SDL_FreeSurface(data->screens[i]); | |
402 } | |
403 } | |
404 SDL_free(data); | |
405 } | |
406 SDL_free(renderer); | |
407 } | |
408 | |
409 /* vi: set ts=4 sw=4 expandtab: */ |