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);