Mercurial > sdl-ios-xcode
comparison src/video/dummy/SDL_nullrender.c @ 1908:e079dafea2bf
Implemented fully featured dummy renderer
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 15 Jul 2006 19:29:42 +0000 |
parents | 06c27a737b7a |
children | 8d384b647307 |
comparison
equal
deleted
inserted
replaced
1907:06c27a737b7a | 1908:e079dafea2bf |
---|---|
21 */ | 21 */ |
22 #include "SDL_config.h" | 22 #include "SDL_config.h" |
23 | 23 |
24 #include "SDL_video.h" | 24 #include "SDL_video.h" |
25 #include "../SDL_sysvideo.h" | 25 #include "../SDL_sysvideo.h" |
26 #include "../SDL_yuv_sw_c.h" | |
26 | 27 |
27 | 28 |
28 /* SDL surface based renderer implementation */ | 29 /* SDL surface based renderer implementation */ |
29 | 30 |
30 static SDL_Renderer *SDL_DUMMY_CreateRenderer(SDL_Window * window, | 31 static SDL_Renderer *SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags); |
31 Uint32 flags); | |
32 static int SDL_DUMMY_CreateTexture(SDL_Renderer * renderer, | 32 static int SDL_DUMMY_CreateTexture(SDL_Renderer * renderer, |
33 SDL_Texture * texture); | 33 SDL_Texture * texture); |
34 static int SDL_DUMMY_QueryTexturePixels(SDL_Renderer * renderer, | |
35 SDL_Texture * texture, void **pixels, | |
36 int *pitch); | |
37 static int SDL_DUMMY_SetTexturePalette(SDL_Renderer * renderer, | |
38 SDL_Texture * texture, | |
39 const SDL_Color * colors, int firstcolor, | |
40 int ncolors); | |
41 static int SDL_DUMMY_GetTexturePalette(SDL_Renderer * renderer, | |
42 SDL_Texture * texture, SDL_Color * colors, | |
43 int firstcolor, int ncolors); | |
44 static int SDL_DUMMY_UpdateTexture(SDL_Renderer * renderer, | |
45 SDL_Texture * texture, const SDL_Rect * rect, | |
46 const void *pixels, int pitch); | |
47 static int SDL_DUMMY_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
48 const SDL_Rect * rect, int markDirty, | |
49 void **pixels, int *pitch); | |
50 static void SDL_DUMMY_UnlockTexture(SDL_Renderer * renderer, | |
51 SDL_Texture * texture); | |
52 static void SDL_DUMMY_DirtyTexture(SDL_Renderer * renderer, | |
53 SDL_Texture * texture, int numrects, | |
54 const SDL_Rect * rects); | |
55 static void SDL_DUMMY_SelectRenderTexture(SDL_Renderer * renderer, | |
56 SDL_Texture * texture); | |
57 static int SDL_DUMMY_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, | |
58 Uint32 color); | |
59 static int SDL_DUMMY_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
60 const SDL_Rect * srcrect, | |
61 const SDL_Rect * dstrect, int blendMode, | |
62 int scaleMode); | |
63 static int SDL_DUMMY_RenderReadPixels(SDL_Renderer * renderer, | |
64 const SDL_Rect * rect, void *pixels, | |
65 int pitch); | |
66 static int SDL_DUMMY_RenderWritePixels(SDL_Renderer * renderer, | |
67 const SDL_Rect * rect, const void *pixels, | |
68 int pitch); | |
34 static void SDL_DUMMY_RenderPresent(SDL_Renderer * renderer); | 69 static void SDL_DUMMY_RenderPresent(SDL_Renderer * renderer); |
70 static void SDL_DUMMY_DestroyTexture(SDL_Renderer * renderer, | |
71 SDL_Texture * texture); | |
35 static void SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer); | 72 static void SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer); |
36 | 73 |
37 | 74 |
38 SDL_RenderDriver SDL_DUMMY_RenderDriver = { | 75 SDL_RenderDriver SDL_DUMMY_RenderDriver = { |
39 SDL_DUMMY_CreateRenderer, | 76 SDL_DUMMY_CreateRenderer, |
40 { | 77 { |
41 "dummy", | 78 "dummy", |
42 (SDL_Renderer_PresentDiscard | SDL_Renderer_PresentCopy), | 79 (SDL_Renderer_SingleBuffer | SDL_Renderer_PresentCopy | |
43 SDL_TextureBlendMode_None, | 80 SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentFlip3 | |
44 SDL_TextureScaleMode_None, | 81 SDL_Renderer_PresentDiscard), |
45 0, | 82 (SDL_TextureBlendMode_None | SDL_TextureBlendMode_Mask | |
46 {0}, | 83 SDL_TextureBlendMode_Blend), |
84 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast), | |
85 11, | |
86 { | |
87 SDL_PixelFormat_Index8, | |
88 SDL_PixelFormat_RGB555, | |
89 SDL_PixelFormat_RGB565, | |
90 SDL_PixelFormat_RGB888, | |
91 SDL_PixelFormat_BGR888, | |
92 SDL_PixelFormat_ARGB8888, | |
93 SDL_PixelFormat_RGBA8888, | |
94 SDL_PixelFormat_ABGR8888, | |
95 SDL_PixelFormat_BGRA8888, | |
96 SDL_PixelFormat_YUY2, | |
97 SDL_PixelFormat_UYVY}, | |
47 0, | 98 0, |
48 0} | 99 0} |
49 }; | 100 }; |
50 | 101 |
51 typedef struct | 102 typedef struct |
52 { | 103 { |
53 SDL_Surface *surface; | 104 int current_screen; |
105 SDL_Surface *screens[3]; | |
54 } SDL_DUMMY_RenderData; | 106 } SDL_DUMMY_RenderData; |
55 | 107 |
56 SDL_Renderer * | 108 SDL_Renderer * |
57 SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags) | 109 SDL_DUMMY_CreateRenderer(SDL_Window * window, Uint32 flags) |
58 { | 110 { |
59 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | 111 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); |
60 SDL_DisplayMode *displayMode = &display->current_mode; | 112 SDL_DisplayMode *displayMode = &display->current_mode; |
61 SDL_Renderer *renderer; | 113 SDL_Renderer *renderer; |
62 SDL_DUMMY_RenderData *data; | 114 SDL_DUMMY_RenderData *data; |
115 int i, n; | |
63 int bpp; | 116 int bpp; |
64 Uint32 Rmask, Gmask, Bmask, Amask; | 117 Uint32 Rmask, Gmask, Bmask, Amask; |
65 | 118 |
66 if (!SDL_PixelFormatEnumToMasks | 119 if (!SDL_PixelFormatEnumToMasks |
67 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | 120 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { |
68 SDL_SetError("Unknown display format"); | 121 SDL_SetError("Unknown display format"); |
69 return NULL; | 122 return NULL; |
70 } | 123 } |
71 | 124 |
72 renderer = (SDL_Renderer *) SDL_malloc(sizeof(*renderer)); | 125 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); |
73 if (!renderer) { | 126 if (!renderer) { |
74 SDL_OutOfMemory(); | 127 SDL_OutOfMemory(); |
75 return NULL; | 128 return NULL; |
76 } | 129 } |
77 SDL_zerop(renderer); | |
78 | 130 |
79 data = (SDL_DUMMY_RenderData *) SDL_malloc(sizeof(*data)); | 131 data = (SDL_DUMMY_RenderData *) SDL_malloc(sizeof(*data)); |
80 if (!data) { | 132 if (!data) { |
81 SDL_DUMMY_DestroyRenderer(renderer); | 133 SDL_DUMMY_DestroyRenderer(renderer); |
82 SDL_OutOfMemory(); | 134 SDL_OutOfMemory(); |
83 return NULL; | 135 return NULL; |
84 } | 136 } |
85 SDL_zerop(data); | 137 SDL_zerop(data); |
86 | 138 |
139 renderer->CreateTexture = SDL_DUMMY_CreateTexture; | |
140 renderer->QueryTexturePixels = SDL_DUMMY_QueryTexturePixels; | |
141 renderer->SetTexturePalette = SDL_DUMMY_SetTexturePalette; | |
142 renderer->GetTexturePalette = SDL_DUMMY_GetTexturePalette; | |
143 renderer->UpdateTexture = SDL_DUMMY_UpdateTexture; | |
144 renderer->LockTexture = SDL_DUMMY_LockTexture; | |
145 renderer->UnlockTexture = SDL_DUMMY_UnlockTexture; | |
146 renderer->DirtyTexture = SDL_DUMMY_DirtyTexture; | |
147 renderer->RenderFill = SDL_DUMMY_RenderFill; | |
148 renderer->RenderCopy = SDL_DUMMY_RenderCopy; | |
87 renderer->RenderPresent = SDL_DUMMY_RenderPresent; | 149 renderer->RenderPresent = SDL_DUMMY_RenderPresent; |
150 renderer->DestroyTexture = SDL_DUMMY_DestroyTexture; | |
88 renderer->DestroyRenderer = SDL_DUMMY_DestroyRenderer; | 151 renderer->DestroyRenderer = SDL_DUMMY_DestroyRenderer; |
89 renderer->info = SDL_DUMMY_RenderDriver.info; | 152 renderer->info = SDL_DUMMY_RenderDriver.info; |
90 renderer->window = window->id; | 153 renderer->window = window->id; |
91 renderer->driverdata = data; | 154 renderer->driverdata = data; |
92 | 155 |
93 data->surface = | 156 renderer->info.flags = 0; |
94 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask, | 157 |
95 Bmask, Amask); | 158 if (flags & SDL_Renderer_PresentFlip2) { |
96 if (!data->surface) { | 159 renderer->info.flags |= SDL_Renderer_PresentFlip2; |
97 SDL_DUMMY_DestroyRenderer(renderer); | 160 n = 2; |
98 return NULL; | 161 } else if (flags & SDL_Renderer_PresentFlip3) { |
99 } | 162 renderer->info.flags |= SDL_Renderer_PresentFlip3; |
100 SDL_SetSurfacePalette(data->surface, display->palette); | 163 n = 3; |
164 } else { | |
165 renderer->info.flags |= SDL_Renderer_PresentCopy; | |
166 n = 1; | |
167 } | |
168 for (i = 0; i < n; ++i) { | |
169 data->screens[i] = | |
170 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask, | |
171 Bmask, Amask); | |
172 if (!data->screens[i]) { | |
173 SDL_DUMMY_DestroyRenderer(renderer); | |
174 return NULL; | |
175 } | |
176 SDL_SetSurfacePalette(data->screens[i], display->palette); | |
177 } | |
178 data->current_screen = 0; | |
101 | 179 |
102 return renderer; | 180 return renderer; |
103 } | 181 } |
104 | 182 |
105 void | 183 static int |
184 SDL_DUMMY_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
185 { | |
186 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
187 texture->driverdata = SDL_SW_CreateYUVTexture(texture); | |
188 } else { | |
189 int bpp; | |
190 Uint32 Rmask, Gmask, Bmask, Amask; | |
191 | |
192 if (!SDL_PixelFormatEnumToMasks | |
193 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
194 SDL_SetError("Unknown texture format"); | |
195 return -1; | |
196 } | |
197 | |
198 texture->driverdata = SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, Bmask, Amask); | |
199 } | |
200 | |
201 if (!texture->driverdata) { | |
202 return -1; | |
203 } | |
204 return 0; | |
205 } | |
206 | |
207 static int | |
208 SDL_DUMMY_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, | |
209 void **pixels, int *pitch) | |
210 { | |
211 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
212 return SDL_SW_QueryYUVTexturePixels((SDL_SW_YUVTexture *) texture->driverdata, pixels, pitch); | |
213 } else { | |
214 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
215 | |
216 *pixels = surface->pixels; | |
217 *pitch = surface->pitch; | |
218 return 0; | |
219 } | |
220 } | |
221 | |
222 static int | |
223 SDL_DUMMY_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture, | |
224 const SDL_Color * colors, int firstcolor, | |
225 int ncolors) | |
226 { | |
227 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
228 SDL_SetError("YUV textures don't have a palette"); | |
229 return -1; | |
230 } else { | |
231 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
232 | |
233 return SDL_SetPaletteColors(surface->format->palette, colors, | |
234 firstcolor, ncolors); | |
235 } | |
236 } | |
237 | |
238 static int | |
239 SDL_DUMMY_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture, | |
240 SDL_Color * colors, int firstcolor, int ncolors) | |
241 { | |
242 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
243 SDL_SetError("YUV textures don't have a palette"); | |
244 return -1; | |
245 } else { | |
246 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
247 | |
248 SDL_memcpy(colors, &surface->format->palette->colors[firstcolor], | |
249 ncolors * sizeof(*colors)); | |
250 return 0; | |
251 } | |
252 } | |
253 | |
254 static int | |
255 SDL_DUMMY_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
256 const SDL_Rect * rect, const void *pixels, int pitch) | |
257 { | |
258 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
259 return SDL_SW_UpdateYUVTexture((SDL_SW_YUVTexture *) texture-> | |
260 driverdata, rect, pixels, pitch); | |
261 } else { | |
262 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
263 Uint8 *src, *dst; | |
264 int row; | |
265 size_t length; | |
266 | |
267 src = (Uint8 *) pixels; | |
268 dst = | |
269 (Uint8 *) surface->pixels + rect->y * surface->pitch + | |
270 rect->x * surface->format->BytesPerPixel; | |
271 length = rect->w * surface->format->BytesPerPixel; | |
272 for (row = 0; row < rect->h; ++row) { | |
273 SDL_memcpy(dst, src, length); | |
274 src += pitch; | |
275 dst += surface->pitch; | |
276 } | |
277 return 0; | |
278 } | |
279 } | |
280 | |
281 static int | |
282 SDL_DUMMY_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
283 const SDL_Rect * rect, int markDirty, void **pixels, | |
284 int *pitch) | |
285 { | |
286 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
287 return SDL_SW_LockYUVTexture((SDL_SW_YUVTexture *) texture-> | |
288 driverdata, rect, markDirty, pixels, | |
289 pitch); | |
290 } else { | |
291 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
292 | |
293 *pixels = | |
294 (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch + | |
295 rect->x * surface->format->BytesPerPixel); | |
296 *pitch = surface->pitch; | |
297 return 0; | |
298 } | |
299 } | |
300 | |
301 static void | |
302 SDL_DUMMY_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
303 { | |
304 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
305 SDL_SW_UnlockYUVTexture((SDL_SW_YUVTexture *) texture->driverdata); | |
306 } | |
307 } | |
308 | |
309 static void | |
310 SDL_DUMMY_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
311 int numrects, const SDL_Rect * rects) | |
312 { | |
313 } | |
314 | |
315 static int | |
316 SDL_DUMMY_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, | |
317 Uint32 color) | |
318 { | |
319 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata; | |
320 SDL_Surface *target = data->screens[data->current_screen]; | |
321 SDL_Rect real_rect = *rect; | |
322 Uint8 r, g, b, a; | |
323 | |
324 a = (Uint8) ((color >> 24) & 0xFF); | |
325 r = (Uint8) ((color >> 16) & 0xFF); | |
326 g = (Uint8) ((color >> 8) & 0xFF); | |
327 b = (Uint8) (color & 0xFF); | |
328 color = SDL_MapRGBA(target->format, r, g, b, a); | |
329 | |
330 return SDL_FillRect(target, &real_rect, color); | |
331 } | |
332 | |
333 static int | |
334 SDL_DUMMY_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
335 const SDL_Rect * srcrect, const SDL_Rect * dstrect, | |
336 int blendMode, int scaleMode) | |
337 { | |
338 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata; | |
339 SDL_Window *window = SDL_GetWindowFromID(renderer->window); | |
340 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | |
341 | |
342 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
343 SDL_Surface *target = data->screens[data->current_screen]; | |
344 void *pixels = | |
345 (Uint8 *) target->pixels + dstrect->y * target->pitch + | |
346 dstrect->x * target->format->BytesPerPixel; | |
347 return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, | |
348 srcrect, display->current_mode.format, | |
349 dstrect->w, dstrect->h, pixels, | |
350 target->pitch); | |
351 } else { | |
352 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
353 SDL_Surface *target = data->screens[data->current_screen]; | |
354 SDL_Rect real_srcrect = *srcrect; | |
355 SDL_Rect real_dstrect = *dstrect; | |
356 | |
357 if (blendMode & | |
358 (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) { | |
359 SDL_SetAlpha(surface, SDL_SRCALPHA, 0); | |
360 } else { | |
361 SDL_SetAlpha(surface, 0, 0); | |
362 } | |
363 if (scaleMode != SDL_TextureScaleMode_None && | |
364 (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) { | |
365 return SDL_SoftStretch(surface, &real_srcrect, target, &real_dstrect); | |
366 } else { | |
367 return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect); | |
368 } | |
369 } | |
370 } | |
371 | |
372 static void | |
106 SDL_DUMMY_RenderPresent(SDL_Renderer * renderer) | 373 SDL_DUMMY_RenderPresent(SDL_Renderer * renderer) |
107 { | 374 { |
108 static int frame_number; | 375 static int frame_number; |
109 SDL_DUMMY_RenderData *data = | 376 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata; |
110 (SDL_DUMMY_RenderData *) renderer->driverdata; | 377 |
111 SDL_Surface *surface = data->surface; | 378 /* Send the data to the display */ |
112 | |
113 if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) { | 379 if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) { |
114 char file[128]; | 380 char file[128]; |
115 SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", | 381 SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp", |
116 renderer->window, ++frame_number); | 382 renderer->window, ++frame_number); |
117 SDL_SaveBMP(surface, file); | 383 SDL_SaveBMP(data->screens[data->current_screen], file); |
118 } | 384 } |
119 } | 385 |
120 | 386 /* Update the flipping chain, if any */ |
121 void | 387 if (renderer->info.flags & SDL_Renderer_PresentFlip2) { |
388 data->current_screen = (data->current_screen + 1) % 2; | |
389 } else if (renderer->info.flags & SDL_Renderer_PresentFlip3) { | |
390 data->current_screen = (data->current_screen + 1) % 3; | |
391 } | |
392 } | |
393 | |
394 static void | |
395 SDL_DUMMY_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
396 { | |
397 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
398 SDL_SW_DestroyYUVTexture((SDL_SW_YUVTexture *) texture->driverdata); | |
399 } else { | |
400 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
401 | |
402 SDL_FreeSurface(surface); | |
403 } | |
404 } | |
405 | |
406 static void | |
122 SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer) | 407 SDL_DUMMY_DestroyRenderer(SDL_Renderer * renderer) |
123 { | 408 { |
124 SDL_DUMMY_RenderData *data = | 409 SDL_DUMMY_RenderData *data = (SDL_DUMMY_RenderData *) renderer->driverdata; |
125 (SDL_DUMMY_RenderData *) renderer->driverdata; | 410 int i; |
126 | 411 |
127 if (data) { | 412 if (data) { |
128 if (data->surface) { | 413 for (i = 0; i < SDL_arraysize(data->screens); ++i) { |
129 data->surface->format->palette = NULL; | 414 if (data->screens[i]) { |
130 SDL_FreeSurface(data->surface); | 415 SDL_FreeSurface(data->screens[i]); |
416 } | |
131 } | 417 } |
132 SDL_free(data); | 418 SDL_free(data); |
133 } | 419 } |
134 SDL_free(renderer); | 420 SDL_free(renderer); |
135 } | 421 } |