Mercurial > sdl-ios-xcode
comparison src/video/SDL_renderer_sw.c @ 1907:06c27a737b7a
Streamlined the API a bit and optimized the software renderer.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 15 Jul 2006 09:46:36 +0000 |
parents | c2a27da60b18 |
children | 092bd3a019c5 |
comparison
equal
deleted
inserted
replaced
1906:0c49855a7a3e | 1907:06c27a737b7a |
---|---|
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_pixels_c.h" | |
26 #include "SDL_rect_c.h" | 27 #include "SDL_rect_c.h" |
27 #include "SDL_yuv_sw_c.h" | 28 #include "SDL_yuv_sw_c.h" |
28 | 29 |
29 | 30 |
30 /* SDL surface based renderer implementation */ | 31 /* SDL surface based renderer implementation */ |
51 static void SDL_SW_UnlockTexture(SDL_Renderer * renderer, | 52 static void SDL_SW_UnlockTexture(SDL_Renderer * renderer, |
52 SDL_Texture * texture); | 53 SDL_Texture * texture); |
53 static void SDL_SW_DirtyTexture(SDL_Renderer * renderer, | 54 static void SDL_SW_DirtyTexture(SDL_Renderer * renderer, |
54 SDL_Texture * texture, int numrects, | 55 SDL_Texture * texture, int numrects, |
55 const SDL_Rect * rects); | 56 const SDL_Rect * rects); |
56 static void SDL_SW_SelectRenderTexture(SDL_Renderer * renderer, | |
57 SDL_Texture * texture); | |
58 static int SDL_SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, | 57 static int SDL_SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, |
59 Uint32 color); | 58 Uint32 color); |
60 static int SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | 59 static int SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, |
61 const SDL_Rect * srcrect, | 60 const SDL_Rect * srcrect, |
62 const SDL_Rect * dstrect, int blendMode, | 61 const SDL_Rect * dstrect, int blendMode, |
63 int scaleMode); | 62 int scaleMode); |
64 static int SDL_SW_RenderReadPixels(SDL_Renderer * renderer, | |
65 const SDL_Rect * rect, void *pixels, | |
66 int pitch); | |
67 static int SDL_SW_RenderWritePixels(SDL_Renderer * renderer, | |
68 const SDL_Rect * rect, const void *pixels, | |
69 int pitch); | |
70 static void SDL_SW_RenderPresent(SDL_Renderer * renderer); | 63 static void SDL_SW_RenderPresent(SDL_Renderer * renderer); |
71 static void SDL_SW_DestroyTexture(SDL_Renderer * renderer, | 64 static void SDL_SW_DestroyTexture(SDL_Renderer * renderer, |
72 SDL_Texture * texture); | 65 SDL_Texture * texture); |
73 static void SDL_SW_DestroyRenderer(SDL_Renderer * renderer); | 66 static void SDL_SW_DestroyRenderer(SDL_Renderer * renderer); |
74 | 67 |
77 SDL_SW_CreateRenderer, | 70 SDL_SW_CreateRenderer, |
78 { | 71 { |
79 "software", | 72 "software", |
80 (SDL_Renderer_SingleBuffer | SDL_Renderer_PresentCopy | | 73 (SDL_Renderer_SingleBuffer | SDL_Renderer_PresentCopy | |
81 SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentFlip3 | | 74 SDL_Renderer_PresentFlip2 | SDL_Renderer_PresentFlip3 | |
82 SDL_Renderer_PresentDiscard | SDL_Renderer_RenderTarget), | 75 SDL_Renderer_PresentDiscard | SDL_Renderer_PresentVSync), |
83 (SDL_TextureBlendMode_None | SDL_TextureBlendMode_Mask | | 76 (SDL_TextureBlendMode_None | SDL_TextureBlendMode_Mask | |
84 SDL_TextureBlendMode_Blend), | 77 SDL_TextureBlendMode_Blend), |
85 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast), | 78 (SDL_TextureScaleMode_None | SDL_TextureScaleMode_Fast), |
86 11, | 79 11, |
87 { | 80 { |
100 0} | 93 0} |
101 }; | 94 }; |
102 | 95 |
103 typedef struct | 96 typedef struct |
104 { | 97 { |
105 int current_screen; | 98 Uint32 format; |
106 SDL_Surface *screens[3]; | 99 int current_texture; |
107 SDL_Surface *target; | 100 SDL_Texture *texture[3]; |
101 SDL_Surface surface; | |
108 SDL_Renderer *renderer; | 102 SDL_Renderer *renderer; |
109 SDL_DirtyRectList dirty; | 103 SDL_DirtyRectList dirty; |
110 SDL_bool makedirty; | |
111 } SDL_SW_RenderData; | 104 } SDL_SW_RenderData; |
105 | |
106 static SDL_Texture * | |
107 CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h) | |
108 { | |
109 SDL_Texture *texture; | |
110 | |
111 texture = (SDL_Texture *) SDL_malloc(sizeof(*texture)); | |
112 if (!texture) { | |
113 SDL_OutOfMemory(); | |
114 return NULL; | |
115 } | |
116 | |
117 SDL_zerop(texture); | |
118 texture->format = format; | |
119 texture->access = SDL_TextureAccess_Local; | |
120 texture->w = w; | |
121 texture->h = h; | |
122 texture->renderer = renderer; | |
123 | |
124 if (renderer->CreateTexture(renderer, texture) < 0) { | |
125 SDL_free(texture); | |
126 return NULL; | |
127 } | |
128 return texture; | |
129 } | |
130 | |
131 static void | |
132 DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
133 { | |
134 renderer->DestroyTexture(renderer, texture); | |
135 SDL_free(texture); | |
136 } | |
137 | |
138 static int | |
139 DisplayPaletteChanged(void *userdata, SDL_Palette * palette) | |
140 { | |
141 SDL_SW_RenderData *data = (SDL_SW_RenderData *) userdata; | |
142 int i; | |
143 | |
144 for (i = 0; i < SDL_arraysize(data->texture); ++i) { | |
145 if (data->texture[i] && data->renderer->SetTexturePalette) { | |
146 data->renderer->SetTexturePalette(data->renderer, | |
147 data->texture[i], | |
148 palette->colors, 0, | |
149 palette->ncolors); | |
150 } | |
151 } | |
152 return 0; | |
153 } | |
112 | 154 |
113 SDL_Renderer * | 155 SDL_Renderer * |
114 SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) | 156 SDL_SW_CreateRenderer(SDL_Window * window, Uint32 flags) |
115 { | 157 { |
116 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | 158 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); |
118 SDL_Renderer *renderer; | 160 SDL_Renderer *renderer; |
119 SDL_SW_RenderData *data; | 161 SDL_SW_RenderData *data; |
120 int i, n; | 162 int i, n; |
121 int bpp; | 163 int bpp; |
122 Uint32 Rmask, Gmask, Bmask, Amask; | 164 Uint32 Rmask, Gmask, Bmask, Amask; |
165 Uint32 renderer_flags; | |
123 | 166 |
124 if (!SDL_PixelFormatEnumToMasks | 167 if (!SDL_PixelFormatEnumToMasks |
125 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | 168 (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { |
126 SDL_SetError("Unknown display format"); | 169 SDL_SetError("Unknown display format"); |
127 return NULL; | 170 return NULL; |
147 renderer->GetTexturePalette = SDL_SW_GetTexturePalette; | 190 renderer->GetTexturePalette = SDL_SW_GetTexturePalette; |
148 renderer->UpdateTexture = SDL_SW_UpdateTexture; | 191 renderer->UpdateTexture = SDL_SW_UpdateTexture; |
149 renderer->LockTexture = SDL_SW_LockTexture; | 192 renderer->LockTexture = SDL_SW_LockTexture; |
150 renderer->UnlockTexture = SDL_SW_UnlockTexture; | 193 renderer->UnlockTexture = SDL_SW_UnlockTexture; |
151 renderer->DirtyTexture = SDL_SW_DirtyTexture; | 194 renderer->DirtyTexture = SDL_SW_DirtyTexture; |
152 renderer->SelectRenderTexture = SDL_SW_SelectRenderTexture; | |
153 renderer->RenderFill = SDL_SW_RenderFill; | 195 renderer->RenderFill = SDL_SW_RenderFill; |
154 renderer->RenderCopy = SDL_SW_RenderCopy; | 196 renderer->RenderCopy = SDL_SW_RenderCopy; |
155 renderer->RenderReadPixels = SDL_SW_RenderReadPixels; | |
156 renderer->RenderWritePixels = SDL_SW_RenderWritePixels; | |
157 renderer->RenderPresent = SDL_SW_RenderPresent; | 197 renderer->RenderPresent = SDL_SW_RenderPresent; |
158 renderer->DestroyTexture = SDL_SW_DestroyTexture; | 198 renderer->DestroyTexture = SDL_SW_DestroyTexture; |
159 renderer->DestroyRenderer = SDL_SW_DestroyRenderer; | 199 renderer->DestroyRenderer = SDL_SW_DestroyRenderer; |
160 renderer->info = SDL_SW_RenderDriver.info; | 200 renderer->info = SDL_SW_RenderDriver.info; |
161 renderer->window = window->id; | 201 renderer->window = window->id; |
162 renderer->driverdata = data; | 202 renderer->driverdata = data; |
163 | 203 |
164 renderer->info.flags = SDL_Renderer_RenderTarget; | 204 renderer->info.flags = 0; |
165 | 205 |
166 if (flags & SDL_Renderer_PresentFlip2) { | 206 if (flags & SDL_Renderer_PresentFlip2) { |
167 renderer->info.flags |= SDL_Renderer_PresentFlip2; | 207 renderer->info.flags |= SDL_Renderer_PresentFlip2; |
168 n = 2; | 208 n = 2; |
169 } else if (flags & SDL_Renderer_PresentFlip3) { | 209 } else if (flags & SDL_Renderer_PresentFlip3) { |
171 n = 3; | 211 n = 3; |
172 } else { | 212 } else { |
173 renderer->info.flags |= SDL_Renderer_PresentCopy; | 213 renderer->info.flags |= SDL_Renderer_PresentCopy; |
174 n = 1; | 214 n = 1; |
175 } | 215 } |
176 for (i = 0; i < n; ++i) { | 216 data->format = displayMode->format; |
177 data->screens[i] = | |
178 SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask, | |
179 Bmask, Amask); | |
180 if (!data->screens[i]) { | |
181 SDL_SW_DestroyRenderer(renderer); | |
182 return NULL; | |
183 } | |
184 SDL_SetSurfacePalette(data->screens[i], display->palette); | |
185 } | |
186 data->current_screen = 0; | |
187 data->target = data->screens[0]; | |
188 data->makedirty = SDL_TRUE; | |
189 | 217 |
190 /* Find a render driver that we can use to display data */ | 218 /* Find a render driver that we can use to display data */ |
219 renderer_flags = (SDL_Renderer_SingleBuffer | | |
220 SDL_Renderer_PresentDiscard); | |
221 if (flags & SDL_Renderer_PresentVSync) { | |
222 renderer_flags |= SDL_Renderer_PresentVSync; | |
223 } | |
191 for (i = 0; i < display->num_render_drivers; ++i) { | 224 for (i = 0; i < display->num_render_drivers; ++i) { |
192 SDL_RenderDriver *driver = &display->render_drivers[i]; | 225 SDL_RenderDriver *driver = &display->render_drivers[i]; |
193 if (driver->info.name != SDL_SW_RenderDriver.info.name) { | 226 if (driver->info.name != SDL_SW_RenderDriver.info.name) { |
194 data->renderer = | 227 data->renderer = driver->CreateRenderer(window, renderer_flags); |
195 driver->CreateRenderer(window, | |
196 (SDL_Renderer_SingleBuffer | | |
197 SDL_Renderer_PresentDiscard)); | |
198 if (data->renderer) { | 228 if (data->renderer) { |
199 break; | 229 break; |
200 } | 230 } |
201 } | 231 } |
202 } | 232 } |
203 if (i == display->num_render_drivers) { | 233 if (i == display->num_render_drivers) { |
204 SDL_SW_DestroyRenderer(renderer); | 234 SDL_SW_DestroyRenderer(renderer); |
205 SDL_SetError("Couldn't find display render driver"); | 235 SDL_SetError("Couldn't find display render driver"); |
206 return NULL; | 236 return NULL; |
207 } | 237 } |
238 if (data->renderer->info.flags & SDL_Renderer_PresentVSync) { | |
239 renderer->info.flags |= SDL_Renderer_PresentVSync; | |
240 } | |
241 | |
242 /* Create the textures we'll use for display */ | |
243 for (i = 0; i < n; ++i) { | |
244 data->texture[i] = | |
245 CreateTexture(data->renderer, data->format, window->w, window->h); | |
246 if (!data->texture[i]) { | |
247 SDL_SW_DestroyRenderer(renderer); | |
248 return NULL; | |
249 } | |
250 } | |
251 data->current_texture = 0; | |
252 | |
253 /* Create a surface we'll use for rendering */ | |
254 data->surface.flags = SDL_PREALLOC; | |
255 data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); | |
256 if (!data->surface.format) { | |
257 SDL_SW_DestroyRenderer(renderer); | |
258 return NULL; | |
259 } | |
260 SDL_SetSurfacePalette(&data->surface, display->palette); | |
261 | |
262 /* Set up a palette watch on the display palette */ | |
263 if (display->palette) { | |
264 SDL_AddPaletteWatch(display->palette, DisplayPaletteChanged, data); | |
265 } | |
266 | |
208 return renderer; | 267 return renderer; |
209 } | 268 } |
210 | 269 |
211 static int | 270 static int |
212 SDL_SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) | 271 SDL_SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) |
213 { | 272 { |
214 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | 273 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { |
215 if (texture->access == SDL_TextureAccess_Render) { | |
216 SDL_SetError("Rendering to YUV format textures is not supported"); | |
217 return -1; | |
218 } | |
219 texture->driverdata = SDL_SW_CreateYUVTexture(texture); | 274 texture->driverdata = SDL_SW_CreateYUVTexture(texture); |
220 } else { | 275 } else { |
221 int bpp; | 276 int bpp; |
222 Uint32 Rmask, Gmask, Bmask, Amask; | 277 Uint32 Rmask, Gmask, Bmask, Amask; |
223 | 278 |
345 SDL_SW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, | 400 SDL_SW_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, |
346 int numrects, const SDL_Rect * rects) | 401 int numrects, const SDL_Rect * rects) |
347 { | 402 { |
348 } | 403 } |
349 | 404 |
350 static void | |
351 SDL_SW_SelectRenderTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
352 { | |
353 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
354 | |
355 if (texture) { | |
356 data->target = (SDL_Surface *) texture->driverdata; | |
357 data->makedirty = SDL_FALSE; | |
358 } else { | |
359 data->target = data->screens[data->current_screen]; | |
360 data->makedirty = SDL_TRUE; | |
361 } | |
362 } | |
363 | |
364 static int | 405 static int |
365 SDL_SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, | 406 SDL_SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect, |
366 Uint32 color) | 407 Uint32 color) |
367 { | 408 { |
368 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | 409 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; |
369 SDL_Rect real_rect = *rect; | |
370 Uint8 r, g, b, a; | 410 Uint8 r, g, b, a; |
371 | 411 void *pixels; |
372 if (data->makedirty) { | 412 int pitch; |
413 SDL_Rect real_rect; | |
414 int status; | |
415 | |
416 if (data->renderer->info.flags & SDL_Renderer_PresentCopy) { | |
373 SDL_AddDirtyRect(&data->dirty, rect); | 417 SDL_AddDirtyRect(&data->dirty, rect); |
374 } | 418 } |
375 | 419 |
376 a = (Uint8) ((color >> 24) & 0xFF); | 420 a = (Uint8) ((color >> 24) & 0xFF); |
377 r = (Uint8) ((color >> 16) & 0xFF); | 421 r = (Uint8) ((color >> 16) & 0xFF); |
378 g = (Uint8) ((color >> 8) & 0xFF); | 422 g = (Uint8) ((color >> 8) & 0xFF); |
379 b = (Uint8) (color & 0xFF); | 423 b = (Uint8) (color & 0xFF); |
380 color = SDL_MapRGBA(data->target->format, r, g, b, a); | 424 color = SDL_MapRGBA(data->surface.format, r, g, b, a); |
381 | 425 |
382 return SDL_FillRect(data->target, &real_rect, color); | 426 if (data->renderer-> |
427 LockTexture(data->renderer, data->texture[data->current_texture], | |
428 rect, 1, &data->surface.pixels, | |
429 &data->surface.pitch) < 0) { | |
430 return -1; | |
431 } | |
432 data->surface.w = rect->w; | |
433 data->surface.h = rect->h; | |
434 data->surface.clip_rect.w = rect->w; | |
435 data->surface.clip_rect.h = rect->h; | |
436 real_rect = data->surface.clip_rect; | |
437 | |
438 status = SDL_FillRect(&data->surface, &real_rect, color); | |
439 | |
440 data->renderer->UnlockTexture(data->renderer, | |
441 data->texture[data->current_texture]); | |
442 return status; | |
383 } | 443 } |
384 | 444 |
385 static int | 445 static int |
386 SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | 446 SDL_SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, |
387 const SDL_Rect * srcrect, const SDL_Rect * dstrect, | 447 const SDL_Rect * srcrect, const SDL_Rect * dstrect, |
388 int blendMode, int scaleMode) | 448 int blendMode, int scaleMode) |
389 { | 449 { |
390 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | 450 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; |
391 SDL_Window *window = SDL_GetWindowFromID(renderer->window); | 451 SDL_Window *window = SDL_GetWindowFromID(renderer->window); |
392 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | 452 int status; |
393 | 453 |
394 if (data->makedirty) { | 454 if (data->renderer->info.flags & SDL_Renderer_PresentCopy) { |
395 SDL_AddDirtyRect(&data->dirty, dstrect); | 455 SDL_AddDirtyRect(&data->dirty, dstrect); |
396 } | 456 } |
397 | 457 |
398 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | 458 if (data->renderer-> |
399 SDL_Surface *target = data->target; | 459 LockTexture(data->renderer, data->texture[data->current_texture], |
400 void *pixels = | 460 dstrect, 1, &data->surface.pixels, |
401 (Uint8 *) target->pixels + dstrect->y * target->pitch + | 461 &data->surface.pitch) < 0) { |
402 dstrect->x * target->format->BytesPerPixel; | 462 return -1; |
403 return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, | 463 } |
404 srcrect, display->current_mode.format, | 464 |
405 dstrect->w, dstrect->h, pixels, | 465 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { |
406 target->pitch); | 466 status = |
467 SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, | |
468 srcrect, data->format, dstrect->w, dstrect->h, | |
469 data->surface.pixels, data->surface.pitch); | |
407 } else { | 470 } else { |
408 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | 471 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; |
409 SDL_Rect real_srcrect = *srcrect; | 472 SDL_Rect real_srcrect = *srcrect; |
410 SDL_Rect real_dstrect = *dstrect; | 473 SDL_Rect real_dstrect; |
474 | |
475 data->surface.w = dstrect->w; | |
476 data->surface.h = dstrect->h; | |
477 data->surface.clip_rect.w = dstrect->w; | |
478 data->surface.clip_rect.h = dstrect->h; | |
479 real_dstrect = data->surface.clip_rect; | |
411 | 480 |
412 if (blendMode & | 481 if (blendMode & |
413 (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) { | 482 (SDL_TextureBlendMode_Mask | SDL_TextureBlendMode_Blend)) { |
414 SDL_SetAlpha(surface, SDL_SRCALPHA, 0); | 483 SDL_SetAlpha(surface, SDL_SRCALPHA, 0); |
415 } else { | 484 } else { |
416 SDL_SetAlpha(surface, 0, 0); | 485 SDL_SetAlpha(surface, 0, 0); |
417 } | 486 } |
418 if (scaleMode != SDL_TextureScaleMode_None && | 487 if (scaleMode != SDL_TextureScaleMode_None && |
419 (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) { | 488 (srcrect->w != dstrect->w || srcrect->h != dstrect->h)) { |
420 return SDL_SoftStretch(surface, &real_srcrect, data->target, | 489 status = |
421 &real_dstrect); | 490 SDL_SoftStretch(surface, &real_srcrect, &data->surface, |
491 &real_dstrect); | |
422 } else { | 492 } else { |
423 return SDL_LowerBlit(surface, &real_srcrect, data->target, | 493 status = |
424 &real_dstrect); | 494 SDL_LowerBlit(surface, &real_srcrect, &data->surface, |
425 } | 495 &real_dstrect); |
426 } | 496 } |
427 } | 497 } |
428 | 498 data->renderer->UnlockTexture(data->renderer, |
429 static int | 499 data->texture[data->current_texture]); |
430 SDL_SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, | 500 return status; |
431 void *pixels, int pitch) | |
432 { | |
433 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
434 SDL_Surface *surface = data->target; | |
435 Uint8 *src, *dst; | |
436 int row; | |
437 size_t length; | |
438 | |
439 src = | |
440 (Uint8 *) surface->pixels + rect->y * surface->pitch + | |
441 rect->x * surface->format->BytesPerPixel; | |
442 dst = (Uint8 *) pixels; | |
443 length = rect->w * surface->format->BytesPerPixel; | |
444 for (row = 0; row < rect->h; ++row) { | |
445 SDL_memcpy(dst, src, length); | |
446 src += surface->pitch; | |
447 dst += pitch; | |
448 } | |
449 return 0; | |
450 } | |
451 | |
452 static int | |
453 SDL_SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, | |
454 const void *pixels, int pitch) | |
455 { | |
456 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | |
457 SDL_Surface *surface = data->target; | |
458 Uint8 *src, *dst; | |
459 int row; | |
460 size_t length; | |
461 | |
462 if (data->makedirty) { | |
463 SDL_AddDirtyRect(&data->dirty, rect); | |
464 } | |
465 | |
466 src = (Uint8 *) pixels; | |
467 dst = | |
468 (Uint8 *) surface->pixels + rect->y * surface->pitch + | |
469 rect->x * surface->format->BytesPerPixel; | |
470 length = rect->w * surface->format->BytesPerPixel; | |
471 for (row = 0; row < rect->h; ++row) { | |
472 SDL_memcpy(dst, src, length); | |
473 src += pitch; | |
474 dst += surface->pitch; | |
475 } | |
476 return 0; | |
477 } | 501 } |
478 | 502 |
479 static void | 503 static void |
480 SDL_SW_RenderPresent(SDL_Renderer * renderer) | 504 SDL_SW_RenderPresent(SDL_Renderer * renderer) |
481 { | 505 { |
482 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | 506 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; |
483 SDL_Surface *surface = data->screens[data->current_screen]; | 507 SDL_Texture *texture = data->texture[data->current_texture]; |
484 SDL_DirtyRect *dirty; | |
485 | 508 |
486 /* Send the data to the display */ | 509 /* Send the data to the display */ |
487 for (dirty = data->dirty.list; dirty; dirty = dirty->next) { | 510 if (data->renderer->info.flags & SDL_Renderer_PresentCopy) { |
488 void *pixels = | 511 SDL_DirtyRect *dirty; |
489 (void *) ((Uint8 *) surface->pixels + | 512 for (dirty = data->dirty.list; dirty; dirty = dirty->next) { |
490 dirty->rect.y * surface->pitch + | 513 data->renderer->RenderCopy(data->renderer, texture, &dirty->rect, |
491 dirty->rect.x * surface->format->BytesPerPixel); | 514 &dirty->rect, |
492 data->renderer->RenderWritePixels(data->renderer, &dirty->rect, | 515 SDL_TextureBlendMode_None, |
493 pixels, surface->pitch); | 516 SDL_TextureScaleMode_None); |
494 } | 517 } |
495 SDL_ClearDirtyRects(&data->dirty); | 518 SDL_ClearDirtyRects(&data->dirty); |
519 } else { | |
520 SDL_Rect rect; | |
521 rect.x = 0; | |
522 rect.y = 0; | |
523 rect.w = texture->w; | |
524 rect.h = texture->h; | |
525 data->renderer->RenderCopy(data->renderer, texture, &rect, &rect, | |
526 SDL_TextureBlendMode_None, | |
527 SDL_TextureScaleMode_None); | |
528 } | |
496 data->renderer->RenderPresent(data->renderer); | 529 data->renderer->RenderPresent(data->renderer); |
497 | 530 |
498 /* Update the flipping chain, if any */ | 531 /* Update the flipping chain, if any */ |
499 if (renderer->info.flags & SDL_Renderer_PresentFlip2) { | 532 if (renderer->info.flags & SDL_Renderer_PresentFlip2) { |
500 data->current_screen = (data->current_screen + 1) % 2; | 533 data->current_texture = (data->current_texture + 1) % 2; |
501 data->target = data->screens[data->current_screen]; | |
502 } else if (renderer->info.flags & SDL_Renderer_PresentFlip3) { | 534 } else if (renderer->info.flags & SDL_Renderer_PresentFlip3) { |
503 data->current_screen = (data->current_screen + 1) % 3; | 535 data->current_texture = (data->current_texture + 1) % 3; |
504 data->target = data->screens[data->current_screen]; | |
505 } | 536 } |
506 } | 537 } |
507 | 538 |
508 static void | 539 static void |
509 SDL_SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | 540 SDL_SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) |
519 | 550 |
520 static void | 551 static void |
521 SDL_SW_DestroyRenderer(SDL_Renderer * renderer) | 552 SDL_SW_DestroyRenderer(SDL_Renderer * renderer) |
522 { | 553 { |
523 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; | 554 SDL_SW_RenderData *data = (SDL_SW_RenderData *) renderer->driverdata; |
555 SDL_Window *window = SDL_GetWindowFromID(renderer->window); | |
556 SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); | |
524 int i; | 557 int i; |
525 | 558 |
526 if (data) { | 559 if (data) { |
527 for (i = 0; i < SDL_arraysize(data->screens); ++i) { | 560 for (i = 0; i < SDL_arraysize(data->texture); ++i) { |
528 if (data->screens[i]) { | 561 if (data->texture[i]) { |
529 SDL_FreeSurface(data->screens[i]); | 562 DestroyTexture(data->renderer, data->texture[i]); |
530 } | 563 } |
564 } | |
565 if (data->surface.format) { | |
566 SDL_SetSurfacePalette(&data->surface, NULL); | |
567 SDL_FreeFormat(data->surface.format); | |
568 } | |
569 if (display->palette) { | |
570 SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged, | |
571 data); | |
572 } | |
573 if (data->renderer) { | |
574 data->renderer->DestroyRenderer(data->renderer); | |
531 } | 575 } |
532 SDL_FreeDirtyRects(&data->dirty); | 576 SDL_FreeDirtyRects(&data->dirty); |
533 SDL_free(data); | 577 SDL_free(data); |
534 } | 578 } |
535 SDL_free(renderer); | 579 SDL_free(renderer); |