comparison src/render/software/SDL_renderer_sw.c @ 5159:307ccc9c135e

Made it possible to create a texture of any format, even if not supported by the renderer. This allows me to reduce the set of formats supported by the renderers to the most optimal set, for a nice speed boost.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 03 Feb 2011 00:19:40 -0800
parents fb424691cfc7
children 657543cc92f9
comparison
equal deleted inserted replaced
5158:f3ebd1950442 5159:307ccc9c135e
21 */ 21 */
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 #include "../SDL_sysrender.h" 24 #include "../SDL_sysrender.h"
25 #include "../../video/SDL_pixels_c.h" 25 #include "../../video/SDL_pixels_c.h"
26 #include "../../video/SDL_yuv_sw_c.h"
27 26
28 27
29 /* SDL surface based renderer implementation */ 28 /* SDL surface based renderer implementation */
30 29
31 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags); 30 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
32 static void SW_WindowEvent(SDL_Renderer * renderer, 31 static void SW_WindowEvent(SDL_Renderer * renderer,
33 const SDL_WindowEvent *event); 32 const SDL_WindowEvent *event);
34 static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); 33 static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
35 static int SW_QueryTexturePixels(SDL_Renderer * renderer,
36 SDL_Texture * texture, void **pixels,
37 int *pitch);
38 static int SW_SetTextureColorMod(SDL_Renderer * renderer, 34 static int SW_SetTextureColorMod(SDL_Renderer * renderer,
39 SDL_Texture * texture); 35 SDL_Texture * texture);
40 static int SW_SetTextureAlphaMod(SDL_Renderer * renderer, 36 static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
41 SDL_Texture * texture); 37 SDL_Texture * texture);
42 static int SW_SetTextureBlendMode(SDL_Renderer * renderer, 38 static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
43 SDL_Texture * texture); 39 SDL_Texture * texture);
44 static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 40 static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
45 const SDL_Rect * rect, const void *pixels, 41 const SDL_Rect * rect, const void *pixels,
46 int pitch); 42 int pitch);
47 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 43 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
48 const SDL_Rect * rect, int markDirty, void **pixels, 44 const SDL_Rect * rect, void **pixels, int *pitch);
49 int *pitch);
50 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); 45 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
51 static int SW_RenderDrawPoints(SDL_Renderer * renderer, 46 static int SW_RenderDrawPoints(SDL_Renderer * renderer,
52 const SDL_Point * points, int count); 47 const SDL_Point * points, int count);
53 static int SW_RenderDrawLines(SDL_Renderer * renderer, 48 static int SW_RenderDrawLines(SDL_Renderer * renderer,
54 const SDL_Point * points, int count); 49 const SDL_Point * points, int count);
68 SDL_RenderDriver SW_RenderDriver = { 63 SDL_RenderDriver SW_RenderDriver = {
69 SW_CreateRenderer, 64 SW_CreateRenderer,
70 { 65 {
71 "software", 66 "software",
72 (SDL_RENDERER_PRESENTVSYNC), 67 (SDL_RENDERER_PRESENTVSYNC),
73 13, 68 8,
74 { 69 {
75 SDL_PIXELFORMAT_RGB555, 70 SDL_PIXELFORMAT_RGB555,
76 SDL_PIXELFORMAT_RGB565, 71 SDL_PIXELFORMAT_RGB565,
77 SDL_PIXELFORMAT_RGB888, 72 SDL_PIXELFORMAT_RGB888,
78 SDL_PIXELFORMAT_BGR888, 73 SDL_PIXELFORMAT_BGR888,
79 SDL_PIXELFORMAT_ARGB8888, 74 SDL_PIXELFORMAT_ARGB8888,
80 SDL_PIXELFORMAT_RGBA8888, 75 SDL_PIXELFORMAT_RGBA8888,
81 SDL_PIXELFORMAT_ABGR8888, 76 SDL_PIXELFORMAT_ABGR8888,
82 SDL_PIXELFORMAT_BGRA8888, 77 SDL_PIXELFORMAT_BGRA8888
83 SDL_PIXELFORMAT_YV12, 78 },
84 SDL_PIXELFORMAT_IYUV,
85 SDL_PIXELFORMAT_YUY2,
86 SDL_PIXELFORMAT_UYVY,
87 SDL_PIXELFORMAT_YVYU},
88 0, 79 0,
89 0} 80 0}
90 }; 81 };
91 82
92 typedef struct 83 typedef struct
94 Uint32 format; 85 Uint32 format;
95 SDL_bool updateSize; 86 SDL_bool updateSize;
96 SDL_Texture *texture; 87 SDL_Texture *texture;
97 SDL_Surface surface; 88 SDL_Surface surface;
98 SDL_Renderer *renderer; 89 SDL_Renderer *renderer;
99 SDL_DirtyRectList dirty;
100 } SW_RenderData; 90 } SW_RenderData;
101 91
102 static SDL_Texture * 92 static SDL_Texture *
103 CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h) 93 CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h)
104 { 94 {
134 SW_CreateRenderer(SDL_Window * window, Uint32 flags) 124 SW_CreateRenderer(SDL_Window * window, Uint32 flags)
135 { 125 {
136 SDL_Renderer *renderer; 126 SDL_Renderer *renderer;
137 SW_RenderData *data; 127 SW_RenderData *data;
138 int i; 128 int i;
129 int w, h;
139 Uint32 format; 130 Uint32 format;
140 int bpp; 131 int bpp;
141 Uint32 Rmask, Gmask, Bmask, Amask; 132 Uint32 Rmask, Gmask, Bmask, Amask;
142 Uint32 renderer_flags; 133 Uint32 renderer_flags;
143 const char *desired_driver; 134 const char *desired_driver;
161 SDL_OutOfMemory(); 152 SDL_OutOfMemory();
162 return NULL; 153 return NULL;
163 } 154 }
164 renderer->WindowEvent = SW_WindowEvent; 155 renderer->WindowEvent = SW_WindowEvent;
165 renderer->CreateTexture = SW_CreateTexture; 156 renderer->CreateTexture = SW_CreateTexture;
166 renderer->QueryTexturePixels = SW_QueryTexturePixels;
167 renderer->SetTextureColorMod = SW_SetTextureColorMod; 157 renderer->SetTextureColorMod = SW_SetTextureColorMod;
168 renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod; 158 renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
169 renderer->SetTextureBlendMode = SW_SetTextureBlendMode; 159 renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
170 renderer->UpdateTexture = SW_UpdateTexture; 160 renderer->UpdateTexture = SW_UpdateTexture;
171 renderer->LockTexture = SW_LockTexture; 161 renderer->LockTexture = SW_LockTexture;
215 if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { 205 if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
216 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; 206 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
217 } 207 }
218 208
219 /* Create the textures we'll use for display */ 209 /* Create the textures we'll use for display */
220 data->texture = 210 SDL_GetWindowSize(window, &w, &h);
221 CreateTexture(data->renderer, data->format, window->w, window->h); 211 data->texture = CreateTexture(data->renderer, data->format, w, h);
222 if (!data->texture) { 212 if (!data->texture) {
223 SW_DestroyRenderer(renderer); 213 SW_DestroyRenderer(renderer);
224 return NULL; 214 return NULL;
225 } 215 }
226 216
241 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 231 SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
242 SDL_Window *window = renderer->window; 232 SDL_Window *window = renderer->window;
243 233
244 if (data->updateSize) { 234 if (data->updateSize) {
245 /* Recreate the textures for the new window size */ 235 /* Recreate the textures for the new window size */
236 int w, h;
246 if (data->texture) { 237 if (data->texture) {
247 DestroyTexture(data->renderer, data->texture); 238 DestroyTexture(data->renderer, data->texture);
248 } 239 }
249 data->texture = CreateTexture(data->renderer, data->format, 240 SDL_GetWindowSize(window, &w, &h);
250 window->w, window->h); 241 data->texture = CreateTexture(data->renderer, data->format, w, h);
251 if (data->texture) { 242 if (data->texture) {
252 data->updateSize = SDL_FALSE; 243 data->updateSize = SDL_FALSE;
253 } 244 }
254 } 245 }
255 return data->texture; 246 return data->texture;
266 } 257 }
267 258
268 static int 259 static int
269 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 260 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
270 { 261 {
271 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 262 int bpp;
272 texture->driverdata = 263 Uint32 Rmask, Gmask, Bmask, Amask;
273 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); 264
274 } else { 265 if (!SDL_PixelFormatEnumToMasks
275 int bpp; 266 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
276 Uint32 Rmask, Gmask, Bmask, Amask; 267 SDL_SetError("Unknown texture format");
277 268 return -1;
278 if (!SDL_PixelFormatEnumToMasks 269 }
279 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { 270
280 SDL_SetError("Unknown texture format"); 271 texture->driverdata =
281 return -1; 272 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
282 } 273 Bmask, Amask);
283 274 SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
284 texture->driverdata = 275 texture->b);
285 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, 276 SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
286 Bmask, Amask); 277 SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
287 SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g, 278
288 texture->b); 279 if (texture->access == SDL_TEXTUREACCESS_STATIC) {
289 SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a); 280 SDL_SetSurfaceRLE(texture->driverdata, 1);
290 SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
291
292 if (texture->access == SDL_TEXTUREACCESS_STATIC) {
293 SDL_SetSurfaceRLE(texture->driverdata, 1);
294 }
295 } 281 }
296 282
297 if (!texture->driverdata) { 283 if (!texture->driverdata) {
298 return -1; 284 return -1;
299 } 285 }
300 return 0; 286 return 0;
301 }
302
303 static int
304 SW_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
305 void **pixels, int *pitch)
306 {
307 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
308 return SDL_SW_QueryYUVTexturePixels((SDL_SW_YUVTexture *)
309 texture->driverdata, pixels,
310 pitch);
311 } else {
312 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
313
314 *pixels = surface->pixels;
315 *pitch = surface->pitch;
316 return 0;
317 }
318 } 287 }
319 288
320 static int 289 static int
321 SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) 290 SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
322 { 291 {
341 310
342 static int 311 static int
343 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 312 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
344 const SDL_Rect * rect, const void *pixels, int pitch) 313 const SDL_Rect * rect, const void *pixels, int pitch)
345 { 314 {
346 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 315 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
347 return SDL_SW_UpdateYUVTexture((SDL_SW_YUVTexture *) 316 Uint8 *src, *dst;
348 texture->driverdata, rect, pixels, 317 int row;
349 pitch); 318 size_t length;
350 } else { 319
351 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 320 src = (Uint8 *) pixels;
352 Uint8 *src, *dst; 321 dst = (Uint8 *) surface->pixels +
353 int row; 322 rect->y * surface->pitch +
354 size_t length; 323 rect->x * surface->format->BytesPerPixel;
355 324 length = rect->w * surface->format->BytesPerPixel;
356 src = (Uint8 *) pixels; 325 for (row = 0; row < rect->h; ++row) {
357 dst = 326 SDL_memcpy(dst, src, length);
358 (Uint8 *) surface->pixels + rect->y * surface->pitch + 327 src += pitch;
359 rect->x * surface->format->BytesPerPixel; 328 dst += surface->pitch;
360 length = rect->w * surface->format->BytesPerPixel; 329 }
361 for (row = 0; row < rect->h; ++row) { 330 return 0;
362 SDL_memcpy(dst, src, length);
363 src += pitch;
364 dst += surface->pitch;
365 }
366 return 0;
367 }
368 } 331 }
369 332
370 static int 333 static int
371 SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 334 SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
372 const SDL_Rect * rect, int markDirty, void **pixels, 335 const SDL_Rect * rect, void **pixels, int *pitch)
373 int *pitch) 336 {
374 { 337 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
375 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 338
376 return SDL_SW_LockYUVTexture((SDL_SW_YUVTexture *) 339 *pixels =
377 texture->driverdata, rect, markDirty, 340 (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
378 pixels, pitch); 341 rect->x * surface->format->BytesPerPixel);
379 } else { 342 *pitch = surface->pitch;
380 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 343 return 0;
381
382 *pixels =
383 (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
384 rect->x * surface->format->BytesPerPixel);
385 *pitch = surface->pitch;
386 return 0;
387 }
388 } 344 }
389 345
390 static void 346 static void
391 SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) 347 SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
392 { 348 {
393 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
394 SDL_SW_UnlockYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
395 }
396 } 349 }
397 350
398 static int 351 static int
399 SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, 352 SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
400 int count) 353 int count)
418 if (!SDL_EnclosePoints(points, count, &rect, &rect)) { 371 if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
419 /* Nothing to draw */ 372 /* Nothing to draw */
420 return 0; 373 return 0;
421 } 374 }
422 375
423 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, 376 if (data->renderer->LockTexture(data->renderer, texture, &rect,
424 &data->surface.pixels, 377 &data->surface.pixels,
425 &data->surface.pitch) < 0) { 378 &data->surface.pitch) < 0) {
426 return -1; 379 return -1;
427 } 380 }
428 381
482 if (!SDL_IntersectRect(&rect, &clip, &rect)) { 435 if (!SDL_IntersectRect(&rect, &clip, &rect)) {
483 /* Nothing to draw */ 436 /* Nothing to draw */
484 return 0; 437 return 0;
485 } 438 }
486 439
487 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, 440 if (data->renderer->LockTexture(data->renderer, texture, &rect,
488 &data->surface.pixels, 441 &data->surface.pixels,
489 &data->surface.pitch) < 0) { 442 &data->surface.pitch) < 0) {
490 return -1; 443 return -1;
491 } 444 }
492 445
556 if (!SDL_IntersectRect(rects[i], &clip, &rect)) { 509 if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
557 /* Nothing to draw */ 510 /* Nothing to draw */
558 continue; 511 continue;
559 } 512 }
560 513
561 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, 514 if (data->renderer->LockTexture(data->renderer, texture, &rect,
562 &data->surface.pixels, 515 &data->surface.pixels,
563 &data->surface.pitch) < 0) { 516 &data->surface.pitch) < 0) {
564 return -1; 517 return -1;
565 } 518 }
566 519
584 static int 537 static int
585 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 538 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
586 const SDL_Rect * srcrect, const SDL_Rect * dstrect) 539 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
587 { 540 {
588 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 541 SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
542 SDL_Surface *surface;
543 SDL_Rect real_srcrect;
544 SDL_Rect real_dstrect;
589 int status; 545 int status;
590 546
591 if (!SW_ActivateRenderer(renderer)) { 547 if (!SW_ActivateRenderer(renderer)) {
592 return -1; 548 return -1;
593 } 549 }
594 550
595 if (data->renderer->LockTexture(data->renderer, data->texture, 551 if (data->renderer->LockTexture(data->renderer, data->texture, dstrect,
596 dstrect, 1, &data->surface.pixels, 552 &data->surface.pixels,
597 &data->surface.pitch) < 0) { 553 &data->surface.pitch) < 0) {
598 return -1; 554 return -1;
599 } 555 }
600 556
601 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 557 surface = (SDL_Surface *) texture->driverdata;
602 status = 558 real_srcrect = *srcrect;
603 SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, 559
604 srcrect, data->format, dstrect->w, dstrect->h, 560 data->surface.w = dstrect->w;
605 data->surface.pixels, data->surface.pitch); 561 data->surface.h = dstrect->h;
606 } else { 562 data->surface.clip_rect.w = dstrect->w;
607 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 563 data->surface.clip_rect.h = dstrect->h;
608 SDL_Rect real_srcrect = *srcrect; 564 real_dstrect = data->surface.clip_rect;
609 SDL_Rect real_dstrect; 565
610 566 status = SDL_LowerBlit(surface, &real_srcrect, &data->surface, &real_dstrect);
611 data->surface.w = dstrect->w;
612 data->surface.h = dstrect->h;
613 data->surface.clip_rect.w = dstrect->w;
614 data->surface.clip_rect.h = dstrect->h;
615 real_dstrect = data->surface.clip_rect;
616
617 status =
618 SDL_LowerBlit(surface, &real_srcrect, &data->surface,
619 &real_dstrect);
620 }
621 data->renderer->UnlockTexture(data->renderer, data->texture); 567 data->renderer->UnlockTexture(data->renderer, data->texture);
622 return status; 568 return status;
623 } 569 }
624 570
625 static int 571 static int
630 576
631 if (!SW_ActivateRenderer(renderer)) { 577 if (!SW_ActivateRenderer(renderer)) {
632 return -1; 578 return -1;
633 } 579 }
634 580
635 if (data->renderer->LockTexture(data->renderer, data->texture, 581 if (data->renderer->LockTexture(data->renderer, data->texture, rect,
636 rect, 0, &data->surface.pixels, 582 &data->surface.pixels,
637 &data->surface.pitch) < 0) { 583 &data->surface.pitch) < 0) {
638 return -1; 584 return -1;
639 } 585 }
640 586
641 SDL_ConvertPixels(rect->w, rect->h, 587 SDL_ConvertPixels(rect->w, rect->h,
654 600
655 if (!SW_ActivateRenderer(renderer)) { 601 if (!SW_ActivateRenderer(renderer)) {
656 return -1; 602 return -1;
657 } 603 }
658 604
659 if (data->renderer->LockTexture(data->renderer, data->texture, 605 if (data->renderer->LockTexture(data->renderer, data->texture, rect,
660 rect, 1, &data->surface.pixels, 606 &data->surface.pixels,
661 &data->surface.pitch) < 0) { 607 &data->surface.pitch) < 0) {
662 return -1; 608 return -1;
663 } 609 }
664 610
665 SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch, 611 SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch,
690 } 636 }
691 637
692 static void 638 static void
693 SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 639 SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
694 { 640 {
695 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { 641 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
696 SDL_SW_DestroyYUVTexture((SDL_SW_YUVTexture *) texture->driverdata); 642
697 } else { 643 SDL_FreeSurface(surface);
698 SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
699
700 SDL_FreeSurface(surface);
701 }
702 } 644 }
703 645
704 static void 646 static void
705 SW_DestroyRenderer(SDL_Renderer * renderer) 647 SW_DestroyRenderer(SDL_Renderer * renderer)
706 { 648 {
715 SDL_FreeFormat(data->surface.format); 657 SDL_FreeFormat(data->surface.format);
716 } 658 }
717 if (data->renderer) { 659 if (data->renderer) {
718 data->renderer->DestroyRenderer(data->renderer); 660 data->renderer->DestroyRenderer(data->renderer);
719 } 661 }
720 SDL_FreeDirtyRects(&data->dirty);
721 SDL_free(data); 662 SDL_free(data);
722 } 663 }
723 SDL_free(renderer); 664 SDL_free(renderer);
724 } 665 }
725 666