SDL_render_sw.c (23409B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if !SDL_RENDER_DISABLED 24 25#include "../SDL_sysrender.h" 26#include "SDL_render_sw_c.h" 27#include "SDL_hints.h" 28 29#include "SDL_draw.h" 30#include "SDL_blendfillrect.h" 31#include "SDL_blendline.h" 32#include "SDL_blendpoint.h" 33#include "SDL_drawline.h" 34#include "SDL_drawpoint.h" 35#include "SDL_rotate.h" 36 37/* SDL surface based renderer implementation */ 38 39static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags); 40static void SW_WindowEvent(SDL_Renderer * renderer, 41 const SDL_WindowEvent *event); 42static int SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h); 43static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); 44static int SW_SetTextureColorMod(SDL_Renderer * renderer, 45 SDL_Texture * texture); 46static int SW_SetTextureAlphaMod(SDL_Renderer * renderer, 47 SDL_Texture * texture); 48static int SW_SetTextureBlendMode(SDL_Renderer * renderer, 49 SDL_Texture * texture); 50static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 51 const SDL_Rect * rect, const void *pixels, 52 int pitch); 53static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 54 const SDL_Rect * rect, void **pixels, int *pitch); 55static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); 56static int SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); 57static int SW_UpdateViewport(SDL_Renderer * renderer); 58static int SW_UpdateClipRect(SDL_Renderer * renderer); 59static int SW_RenderClear(SDL_Renderer * renderer); 60static int SW_RenderDrawPoints(SDL_Renderer * renderer, 61 const SDL_FPoint * points, int count); 62static int SW_RenderDrawLines(SDL_Renderer * renderer, 63 const SDL_FPoint * points, int count); 64static int SW_RenderFillRects(SDL_Renderer * renderer, 65 const SDL_FRect * rects, int count); 66static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 67 const SDL_Rect * srcrect, const SDL_FRect * dstrect); 68static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, 69 const SDL_Rect * srcrect, const SDL_FRect * dstrect, 70 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip); 71static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 72 Uint32 format, void * pixels, int pitch); 73static void SW_RenderPresent(SDL_Renderer * renderer); 74static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); 75static void SW_DestroyRenderer(SDL_Renderer * renderer); 76 77 78SDL_RenderDriver SW_RenderDriver = { 79 SW_CreateRenderer, 80 { 81 "software", 82 SDL_RENDERER_SOFTWARE | SDL_RENDERER_TARGETTEXTURE, 83 8, 84 { 85 SDL_PIXELFORMAT_ARGB8888, 86 SDL_PIXELFORMAT_ABGR8888, 87 SDL_PIXELFORMAT_RGBA8888, 88 SDL_PIXELFORMAT_BGRA8888, 89 SDL_PIXELFORMAT_RGB888, 90 SDL_PIXELFORMAT_BGR888, 91 SDL_PIXELFORMAT_RGB565, 92 SDL_PIXELFORMAT_RGB555 93 }, 94 0, 95 0} 96}; 97 98typedef struct 99{ 100 SDL_Surface *surface; 101 SDL_Surface *window; 102} SW_RenderData; 103 104 105static SDL_Surface * 106SW_ActivateRenderer(SDL_Renderer * renderer) 107{ 108 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 109 110 if (!data->surface) { 111 data->surface = data->window; 112 } 113 if (!data->surface) { 114 SDL_Surface *surface = SDL_GetWindowSurface(renderer->window); 115 if (surface) { 116 data->surface = data->window = surface; 117 118 SW_UpdateViewport(renderer); 119 SW_UpdateClipRect(renderer); 120 } 121 } 122 return data->surface; 123} 124 125SDL_Renderer * 126SW_CreateRendererForSurface(SDL_Surface * surface) 127{ 128 SDL_Renderer *renderer; 129 SW_RenderData *data; 130 131 if (!surface) { 132 SDL_SetError("Can't create renderer for NULL surface"); 133 return NULL; 134 } 135 136 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); 137 if (!renderer) { 138 SDL_OutOfMemory(); 139 return NULL; 140 } 141 142 data = (SW_RenderData *) SDL_calloc(1, sizeof(*data)); 143 if (!data) { 144 SW_DestroyRenderer(renderer); 145 SDL_OutOfMemory(); 146 return NULL; 147 } 148 data->surface = surface; 149 data->window = surface; 150 151 renderer->WindowEvent = SW_WindowEvent; 152 renderer->GetOutputSize = SW_GetOutputSize; 153 renderer->CreateTexture = SW_CreateTexture; 154 renderer->SetTextureColorMod = SW_SetTextureColorMod; 155 renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod; 156 renderer->SetTextureBlendMode = SW_SetTextureBlendMode; 157 renderer->UpdateTexture = SW_UpdateTexture; 158 renderer->LockTexture = SW_LockTexture; 159 renderer->UnlockTexture = SW_UnlockTexture; 160 renderer->SetRenderTarget = SW_SetRenderTarget; 161 renderer->UpdateViewport = SW_UpdateViewport; 162 renderer->UpdateClipRect = SW_UpdateClipRect; 163 renderer->RenderClear = SW_RenderClear; 164 renderer->RenderDrawPoints = SW_RenderDrawPoints; 165 renderer->RenderDrawLines = SW_RenderDrawLines; 166 renderer->RenderFillRects = SW_RenderFillRects; 167 renderer->RenderCopy = SW_RenderCopy; 168 renderer->RenderCopyEx = SW_RenderCopyEx; 169 renderer->RenderReadPixels = SW_RenderReadPixels; 170 renderer->RenderPresent = SW_RenderPresent; 171 renderer->DestroyTexture = SW_DestroyTexture; 172 renderer->DestroyRenderer = SW_DestroyRenderer; 173 renderer->info = SW_RenderDriver.info; 174 renderer->driverdata = data; 175 176 SW_ActivateRenderer(renderer); 177 178 return renderer; 179} 180 181SDL_Renderer * 182SW_CreateRenderer(SDL_Window * window, Uint32 flags) 183{ 184 SDL_Surface *surface; 185 186 surface = SDL_GetWindowSurface(window); 187 if (!surface) { 188 return NULL; 189 } 190 return SW_CreateRendererForSurface(surface); 191} 192 193static void 194SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) 195{ 196 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 197 198 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) { 199 data->surface = NULL; 200 data->window = NULL; 201 } 202} 203 204static int 205SW_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) 206{ 207 SDL_Surface *surface = SW_ActivateRenderer(renderer); 208 209 if (surface) { 210 if (w) { 211 *w = surface->w; 212 } 213 if (h) { 214 *h = surface->h; 215 } 216 return 0; 217 } else { 218 SDL_SetError("Software renderer doesn't have an output surface"); 219 return -1; 220 } 221} 222 223static int 224SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 225{ 226 int bpp; 227 Uint32 Rmask, Gmask, Bmask, Amask; 228 229 if (!SDL_PixelFormatEnumToMasks 230 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { 231 return SDL_SetError("Unknown texture format"); 232 } 233 234 texture->driverdata = 235 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, 236 Bmask, Amask); 237 SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g, 238 texture->b); 239 SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a); 240 SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode); 241 242 if (texture->access == SDL_TEXTUREACCESS_STATIC) { 243 SDL_SetSurfaceRLE(texture->driverdata, 1); 244 } 245 246 if (!texture->driverdata) { 247 return -1; 248 } 249 return 0; 250} 251 252static int 253SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) 254{ 255 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 256 return SDL_SetSurfaceColorMod(surface, texture->r, texture->g, 257 texture->b); 258} 259 260static int 261SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) 262{ 263 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 264 return SDL_SetSurfaceAlphaMod(surface, texture->a); 265} 266 267static int 268SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) 269{ 270 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 271 return SDL_SetSurfaceBlendMode(surface, texture->blendMode); 272} 273 274static int 275SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 276 const SDL_Rect * rect, const void *pixels, int pitch) 277{ 278 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 279 Uint8 *src, *dst; 280 int row; 281 size_t length; 282 283 if(SDL_MUSTLOCK(surface)) 284 SDL_LockSurface(surface); 285 src = (Uint8 *) pixels; 286 dst = (Uint8 *) surface->pixels + 287 rect->y * surface->pitch + 288 rect->x * surface->format->BytesPerPixel; 289 length = rect->w * surface->format->BytesPerPixel; 290 for (row = 0; row < rect->h; ++row) { 291 SDL_memcpy(dst, src, length); 292 src += pitch; 293 dst += surface->pitch; 294 } 295 if(SDL_MUSTLOCK(surface)) 296 SDL_UnlockSurface(surface); 297 return 0; 298} 299 300static int 301SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 302 const SDL_Rect * rect, void **pixels, int *pitch) 303{ 304 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 305 306 *pixels = 307 (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch + 308 rect->x * surface->format->BytesPerPixel); 309 *pitch = surface->pitch; 310 return 0; 311} 312 313static void 314SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) 315{ 316} 317 318static int 319SW_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) 320{ 321 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 322 323 if (texture ) { 324 data->surface = (SDL_Surface *) texture->driverdata; 325 } else { 326 data->surface = data->window; 327 } 328 return 0; 329} 330 331static int 332SW_UpdateViewport(SDL_Renderer * renderer) 333{ 334 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 335 SDL_Surface *surface = data->surface; 336 337 if (!surface) { 338 /* We'll update the viewport after we recreate the surface */ 339 return 0; 340 } 341 342 SDL_SetClipRect(data->surface, &renderer->viewport); 343 return 0; 344} 345 346static int 347SW_UpdateClipRect(SDL_Renderer * renderer) 348{ 349 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 350 SDL_Surface *surface = data->surface; 351 if (surface) { 352 if (renderer->clipping_enabled) { 353 SDL_SetClipRect(surface, &renderer->clip_rect); 354 } else { 355 SDL_SetClipRect(surface, NULL); 356 } 357 } 358 return 0; 359} 360 361static int 362SW_RenderClear(SDL_Renderer * renderer) 363{ 364 SDL_Surface *surface = SW_ActivateRenderer(renderer); 365 Uint32 color; 366 SDL_Rect clip_rect; 367 368 if (!surface) { 369 return -1; 370 } 371 372 color = SDL_MapRGBA(surface->format, 373 renderer->r, renderer->g, renderer->b, renderer->a); 374 375 /* By definition the clear ignores the clip rect */ 376 clip_rect = surface->clip_rect; 377 SDL_SetClipRect(surface, NULL); 378 SDL_FillRect(surface, NULL, color); 379 SDL_SetClipRect(surface, &clip_rect); 380 return 0; 381} 382 383static int 384SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points, 385 int count) 386{ 387 SDL_Surface *surface = SW_ActivateRenderer(renderer); 388 SDL_Point *final_points; 389 int i, status; 390 391 if (!surface) { 392 return -1; 393 } 394 395 final_points = SDL_stack_alloc(SDL_Point, count); 396 if (!final_points) { 397 return SDL_OutOfMemory(); 398 } 399 if (renderer->viewport.x || renderer->viewport.y) { 400 int x = renderer->viewport.x; 401 int y = renderer->viewport.y; 402 403 for (i = 0; i < count; ++i) { 404 final_points[i].x = (int)(x + points[i].x); 405 final_points[i].y = (int)(y + points[i].y); 406 } 407 } else { 408 for (i = 0; i < count; ++i) { 409 final_points[i].x = (int)points[i].x; 410 final_points[i].y = (int)points[i].y; 411 } 412 } 413 414 /* Draw the points! */ 415 if (renderer->blendMode == SDL_BLENDMODE_NONE) { 416 Uint32 color = SDL_MapRGBA(surface->format, 417 renderer->r, renderer->g, renderer->b, 418 renderer->a); 419 420 status = SDL_DrawPoints(surface, final_points, count, color); 421 } else { 422 status = SDL_BlendPoints(surface, final_points, count, 423 renderer->blendMode, 424 renderer->r, renderer->g, renderer->b, 425 renderer->a); 426 } 427 SDL_stack_free(final_points); 428 429 return status; 430} 431 432static int 433SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points, 434 int count) 435{ 436 SDL_Surface *surface = SW_ActivateRenderer(renderer); 437 SDL_Point *final_points; 438 int i, status; 439 440 if (!surface) { 441 return -1; 442 } 443 444 final_points = SDL_stack_alloc(SDL_Point, count); 445 if (!final_points) { 446 return SDL_OutOfMemory(); 447 } 448 if (renderer->viewport.x || renderer->viewport.y) { 449 int x = renderer->viewport.x; 450 int y = renderer->viewport.y; 451 452 for (i = 0; i < count; ++i) { 453 final_points[i].x = (int)(x + points[i].x); 454 final_points[i].y = (int)(y + points[i].y); 455 } 456 } else { 457 for (i = 0; i < count; ++i) { 458 final_points[i].x = (int)points[i].x; 459 final_points[i].y = (int)points[i].y; 460 } 461 } 462 463 /* Draw the lines! */ 464 if (renderer->blendMode == SDL_BLENDMODE_NONE) { 465 Uint32 color = SDL_MapRGBA(surface->format, 466 renderer->r, renderer->g, renderer->b, 467 renderer->a); 468 469 status = SDL_DrawLines(surface, final_points, count, color); 470 } else { 471 status = SDL_BlendLines(surface, final_points, count, 472 renderer->blendMode, 473 renderer->r, renderer->g, renderer->b, 474 renderer->a); 475 } 476 SDL_stack_free(final_points); 477 478 return status; 479} 480 481static int 482SW_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count) 483{ 484 SDL_Surface *surface = SW_ActivateRenderer(renderer); 485 SDL_Rect *final_rects; 486 int i, status; 487 488 if (!surface) { 489 return -1; 490 } 491 492 final_rects = SDL_stack_alloc(SDL_Rect, count); 493 if (!final_rects) { 494 return SDL_OutOfMemory(); 495 } 496 if (renderer->viewport.x || renderer->viewport.y) { 497 int x = renderer->viewport.x; 498 int y = renderer->viewport.y; 499 500 for (i = 0; i < count; ++i) { 501 final_rects[i].x = (int)(x + rects[i].x); 502 final_rects[i].y = (int)(y + rects[i].y); 503 final_rects[i].w = SDL_max((int)rects[i].w, 1); 504 final_rects[i].h = SDL_max((int)rects[i].h, 1); 505 } 506 } else { 507 for (i = 0; i < count; ++i) { 508 final_rects[i].x = (int)rects[i].x; 509 final_rects[i].y = (int)rects[i].y; 510 final_rects[i].w = SDL_max((int)rects[i].w, 1); 511 final_rects[i].h = SDL_max((int)rects[i].h, 1); 512 } 513 } 514 515 if (renderer->blendMode == SDL_BLENDMODE_NONE) { 516 Uint32 color = SDL_MapRGBA(surface->format, 517 renderer->r, renderer->g, renderer->b, 518 renderer->a); 519 status = SDL_FillRects(surface, final_rects, count, color); 520 } else { 521 status = SDL_BlendFillRects(surface, final_rects, count, 522 renderer->blendMode, 523 renderer->r, renderer->g, renderer->b, 524 renderer->a); 525 } 526 SDL_stack_free(final_rects); 527 528 return status; 529} 530 531static int 532SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 533 const SDL_Rect * srcrect, const SDL_FRect * dstrect) 534{ 535 SDL_Surface *surface = SW_ActivateRenderer(renderer); 536 SDL_Surface *src = (SDL_Surface *) texture->driverdata; 537 SDL_Rect final_rect; 538 539 if (!surface) { 540 return -1; 541 } 542 543 if (renderer->viewport.x || renderer->viewport.y) { 544 final_rect.x = (int)(renderer->viewport.x + dstrect->x); 545 final_rect.y = (int)(renderer->viewport.y + dstrect->y); 546 } else { 547 final_rect.x = (int)dstrect->x; 548 final_rect.y = (int)dstrect->y; 549 } 550 final_rect.w = (int)dstrect->w; 551 final_rect.h = (int)dstrect->h; 552 553 if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) { 554 return SDL_BlitSurface(src, srcrect, surface, &final_rect); 555 } else { 556 return SDL_BlitScaled(src, srcrect, surface, &final_rect); 557 } 558} 559 560static int 561GetScaleQuality(void) 562{ 563 const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); 564 565 if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) { 566 return 0; 567 } else { 568 return 1; 569 } 570} 571 572static int 573SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, 574 const SDL_Rect * srcrect, const SDL_FRect * dstrect, 575 const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) 576{ 577 SDL_Surface *surface = SW_ActivateRenderer(renderer); 578 SDL_Surface *src = (SDL_Surface *) texture->driverdata; 579 SDL_Rect final_rect, tmp_rect; 580 SDL_Surface *surface_rotated, *surface_scaled; 581 Uint32 colorkey; 582 int retval, dstwidth, dstheight, abscenterx, abscentery; 583 double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; 584 585 if (!surface) { 586 return -1; 587 } 588 589 if (renderer->viewport.x || renderer->viewport.y) { 590 final_rect.x = (int)(renderer->viewport.x + dstrect->x); 591 final_rect.y = (int)(renderer->viewport.y + dstrect->y); 592 } else { 593 final_rect.x = (int)dstrect->x; 594 final_rect.y = (int)dstrect->y; 595 } 596 final_rect.w = (int)dstrect->w; 597 final_rect.h = (int)dstrect->h; 598 599 surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel, 600 src->format->Rmask, src->format->Gmask, 601 src->format->Bmask, src->format->Amask ); 602 if (surface_scaled) { 603 SDL_GetColorKey(src, &colorkey); 604 SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey); 605 tmp_rect = final_rect; 606 tmp_rect.x = 0; 607 tmp_rect.y = 0; 608 609 retval = SDL_BlitScaled(src, srcrect, surface_scaled, &tmp_rect); 610 if (!retval) { 611 SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, -angle, &dstwidth, &dstheight, &cangle, &sangle); 612 surface_rotated = SDLgfx_rotateSurface(surface_scaled, -angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle); 613 if(surface_rotated) { 614 /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */ 615 abscenterx = final_rect.x + (int)center->x; 616 abscentery = final_rect.y + (int)center->y; 617 /* Compensate the angle inversion to match the behaviour of the other backends */ 618 sangle = -sangle; 619 620 /* Top Left */ 621 px = final_rect.x - abscenterx; 622 py = final_rect.y - abscentery; 623 p1x = px * cangle - py * sangle + abscenterx; 624 p1y = px * sangle + py * cangle + abscentery; 625 626 /* Top Right */ 627 px = final_rect.x + final_rect.w - abscenterx; 628 py = final_rect.y - abscentery; 629 p2x = px * cangle - py * sangle + abscenterx; 630 p2y = px * sangle + py * cangle + abscentery; 631 632 /* Bottom Left */ 633 px = final_rect.x - abscenterx; 634 py = final_rect.y + final_rect.h - abscentery; 635 p3x = px * cangle - py * sangle + abscenterx; 636 p3y = px * sangle + py * cangle + abscentery; 637 638 /* Bottom Right */ 639 px = final_rect.x + final_rect.w - abscenterx; 640 py = final_rect.y + final_rect.h - abscentery; 641 p4x = px * cangle - py * sangle + abscenterx; 642 p4y = px * sangle + py * cangle + abscentery; 643 644 tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x)); 645 tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y)); 646 tmp_rect.w = dstwidth; 647 tmp_rect.h = dstheight; 648 649 retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect); 650 SDL_FreeSurface(surface_scaled); 651 SDL_FreeSurface(surface_rotated); 652 return retval; 653 } 654 } 655 return retval; 656 } 657 658 return -1; 659} 660 661static int 662SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 663 Uint32 format, void * pixels, int pitch) 664{ 665 SDL_Surface *surface = SW_ActivateRenderer(renderer); 666 Uint32 src_format; 667 void *src_pixels; 668 SDL_Rect final_rect; 669 670 if (!surface) { 671 return -1; 672 } 673 674 if (renderer->viewport.x || renderer->viewport.y) { 675 final_rect.x = renderer->viewport.x + rect->x; 676 final_rect.y = renderer->viewport.y + rect->y; 677 final_rect.w = rect->w; 678 final_rect.h = rect->h; 679 rect = &final_rect; 680 } 681 682 if (rect->x < 0 || rect->x+rect->w > surface->w || 683 rect->y < 0 || rect->y+rect->h > surface->h) { 684 return SDL_SetError("Tried to read outside of surface bounds"); 685 } 686 687 src_format = surface->format->format; 688 src_pixels = (void*)((Uint8 *) surface->pixels + 689 rect->y * surface->pitch + 690 rect->x * surface->format->BytesPerPixel); 691 692 return SDL_ConvertPixels(rect->w, rect->h, 693 src_format, src_pixels, surface->pitch, 694 format, pixels, pitch); 695} 696 697static void 698SW_RenderPresent(SDL_Renderer * renderer) 699{ 700 SDL_Window *window = renderer->window; 701 702 if (window) { 703 SDL_UpdateWindowSurface(window); 704 } 705} 706 707static void 708SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 709{ 710 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; 711 712 SDL_FreeSurface(surface); 713} 714 715static void 716SW_DestroyRenderer(SDL_Renderer * renderer) 717{ 718 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; 719 720 SDL_free(data); 721 SDL_free(renderer); 722} 723 724#endif /* !SDL_RENDER_DISABLED */ 725 726/* vi: set ts=4 sw=4 expandtab: */