Mercurial > sdl-ios-xcode
comparison src/render/software/SDL_renderer_sw.c @ 5157:fb424691cfc7
Moved the rendering code out to a separate directory in the hope that it can someday be completely decoupled from the rest of the library and be expanded to an awesome 2D on 3D library.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 02 Feb 2011 14:34:54 -0800 |
parents | src/video/SDL_renderer_sw.c@be02be2ea897 |
children | 307ccc9c135e |
comparison
equal
deleted
inserted
replaced
5156:3e4086b3bcd2 | 5157:fb424691cfc7 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2010 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this library; if not, write to the Free Software | |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 #include "SDL_config.h" | |
23 | |
24 #include "../SDL_sysrender.h" | |
25 #include "../../video/SDL_pixels_c.h" | |
26 #include "../../video/SDL_yuv_sw_c.h" | |
27 | |
28 | |
29 /* SDL surface based renderer implementation */ | |
30 | |
31 static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags); | |
32 static void SW_WindowEvent(SDL_Renderer * renderer, | |
33 const SDL_WindowEvent *event); | |
34 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, | |
39 SDL_Texture * texture); | |
40 static int SW_SetTextureAlphaMod(SDL_Renderer * renderer, | |
41 SDL_Texture * texture); | |
42 static int SW_SetTextureBlendMode(SDL_Renderer * renderer, | |
43 SDL_Texture * texture); | |
44 static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
45 const SDL_Rect * rect, const void *pixels, | |
46 int pitch); | |
47 static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
48 const SDL_Rect * rect, int markDirty, void **pixels, | |
49 int *pitch); | |
50 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); | |
51 static int SW_RenderDrawPoints(SDL_Renderer * renderer, | |
52 const SDL_Point * points, int count); | |
53 static int SW_RenderDrawLines(SDL_Renderer * renderer, | |
54 const SDL_Point * points, int count); | |
55 static int SW_RenderFillRects(SDL_Renderer * renderer, | |
56 const SDL_Rect ** rects, int count); | |
57 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
58 const SDL_Rect * srcrect, const SDL_Rect * dstrect); | |
59 static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, | |
60 Uint32 format, void * pixels, int pitch); | |
61 static int SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, | |
62 Uint32 format, const void * pixels, int pitch); | |
63 static void SW_RenderPresent(SDL_Renderer * renderer); | |
64 static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); | |
65 static void SW_DestroyRenderer(SDL_Renderer * renderer); | |
66 | |
67 | |
68 SDL_RenderDriver SW_RenderDriver = { | |
69 SW_CreateRenderer, | |
70 { | |
71 "software", | |
72 (SDL_RENDERER_PRESENTVSYNC), | |
73 13, | |
74 { | |
75 SDL_PIXELFORMAT_RGB555, | |
76 SDL_PIXELFORMAT_RGB565, | |
77 SDL_PIXELFORMAT_RGB888, | |
78 SDL_PIXELFORMAT_BGR888, | |
79 SDL_PIXELFORMAT_ARGB8888, | |
80 SDL_PIXELFORMAT_RGBA8888, | |
81 SDL_PIXELFORMAT_ABGR8888, | |
82 SDL_PIXELFORMAT_BGRA8888, | |
83 SDL_PIXELFORMAT_YV12, | |
84 SDL_PIXELFORMAT_IYUV, | |
85 SDL_PIXELFORMAT_YUY2, | |
86 SDL_PIXELFORMAT_UYVY, | |
87 SDL_PIXELFORMAT_YVYU}, | |
88 0, | |
89 0} | |
90 }; | |
91 | |
92 typedef struct | |
93 { | |
94 Uint32 format; | |
95 SDL_bool updateSize; | |
96 SDL_Texture *texture; | |
97 SDL_Surface surface; | |
98 SDL_Renderer *renderer; | |
99 SDL_DirtyRectList dirty; | |
100 } SW_RenderData; | |
101 | |
102 static SDL_Texture * | |
103 CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h) | |
104 { | |
105 SDL_Texture *texture; | |
106 | |
107 texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture)); | |
108 if (!texture) { | |
109 SDL_OutOfMemory(); | |
110 return NULL; | |
111 } | |
112 | |
113 texture->format = format; | |
114 texture->access = SDL_TEXTUREACCESS_STREAMING; | |
115 texture->w = w; | |
116 texture->h = h; | |
117 texture->renderer = renderer; | |
118 | |
119 if (renderer->CreateTexture(renderer, texture) < 0) { | |
120 SDL_free(texture); | |
121 return NULL; | |
122 } | |
123 return texture; | |
124 } | |
125 | |
126 static void | |
127 DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
128 { | |
129 renderer->DestroyTexture(renderer, texture); | |
130 SDL_free(texture); | |
131 } | |
132 | |
133 SDL_Renderer * | |
134 SW_CreateRenderer(SDL_Window * window, Uint32 flags) | |
135 { | |
136 SDL_Renderer *renderer; | |
137 SW_RenderData *data; | |
138 int i; | |
139 Uint32 format; | |
140 int bpp; | |
141 Uint32 Rmask, Gmask, Bmask, Amask; | |
142 Uint32 renderer_flags; | |
143 const char *desired_driver; | |
144 | |
145 format = SDL_GetWindowPixelFormat(window); | |
146 if (!SDL_PixelFormatEnumToMasks | |
147 (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
148 SDL_SetError("Unknown display format"); | |
149 return NULL; | |
150 } | |
151 | |
152 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); | |
153 if (!renderer) { | |
154 SDL_OutOfMemory(); | |
155 return NULL; | |
156 } | |
157 | |
158 data = (SW_RenderData *) SDL_calloc(1, sizeof(*data)); | |
159 if (!data) { | |
160 SW_DestroyRenderer(renderer); | |
161 SDL_OutOfMemory(); | |
162 return NULL; | |
163 } | |
164 renderer->WindowEvent = SW_WindowEvent; | |
165 renderer->CreateTexture = SW_CreateTexture; | |
166 renderer->QueryTexturePixels = SW_QueryTexturePixels; | |
167 renderer->SetTextureColorMod = SW_SetTextureColorMod; | |
168 renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod; | |
169 renderer->SetTextureBlendMode = SW_SetTextureBlendMode; | |
170 renderer->UpdateTexture = SW_UpdateTexture; | |
171 renderer->LockTexture = SW_LockTexture; | |
172 renderer->UnlockTexture = SW_UnlockTexture; | |
173 renderer->DestroyTexture = SW_DestroyTexture; | |
174 renderer->RenderDrawPoints = SW_RenderDrawPoints; | |
175 renderer->RenderDrawLines = SW_RenderDrawLines; | |
176 renderer->RenderFillRects = SW_RenderFillRects; | |
177 renderer->RenderCopy = SW_RenderCopy; | |
178 renderer->RenderReadPixels = SW_RenderReadPixels; | |
179 renderer->RenderWritePixels = SW_RenderWritePixels; | |
180 renderer->RenderPresent = SW_RenderPresent; | |
181 renderer->DestroyRenderer = SW_DestroyRenderer; | |
182 renderer->info = SW_RenderDriver.info; | |
183 renderer->info.flags = 0; | |
184 renderer->window = window; | |
185 renderer->driverdata = data; | |
186 | |
187 data->format = format; | |
188 | |
189 /* Find a render driver that we can use to display data */ | |
190 renderer_flags = 0; | |
191 if (flags & SDL_RENDERER_PRESENTVSYNC) { | |
192 renderer_flags |= SDL_RENDERER_PRESENTVSYNC; | |
193 } | |
194 desired_driver = SDL_getenv("SDL_VIDEO_RENDERER_SWDRIVER"); | |
195 for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) { | |
196 SDL_RendererInfo info; | |
197 SDL_GetRenderDriverInfo(i, &info); | |
198 if (SDL_strcmp(info.name, SW_RenderDriver.info.name) == 0) { | |
199 continue; | |
200 } | |
201 if (desired_driver | |
202 && SDL_strcasecmp(desired_driver, info.name) != 0) { | |
203 continue; | |
204 } | |
205 data->renderer = SDL_CreateRenderer(window, i, renderer_flags); | |
206 if (data->renderer) { | |
207 break; | |
208 } | |
209 } | |
210 if (i == SDL_GetNumRenderDrivers()) { | |
211 SW_DestroyRenderer(renderer); | |
212 SDL_SetError("Couldn't find display render driver"); | |
213 return NULL; | |
214 } | |
215 if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { | |
216 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; | |
217 } | |
218 | |
219 /* Create the textures we'll use for display */ | |
220 data->texture = | |
221 CreateTexture(data->renderer, data->format, window->w, window->h); | |
222 if (!data->texture) { | |
223 SW_DestroyRenderer(renderer); | |
224 return NULL; | |
225 } | |
226 | |
227 /* Create a surface we'll use for rendering */ | |
228 data->surface.flags = SDL_PREALLOC; | |
229 data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); | |
230 if (!data->surface.format) { | |
231 SW_DestroyRenderer(renderer); | |
232 return NULL; | |
233 } | |
234 | |
235 return renderer; | |
236 } | |
237 | |
238 static SDL_Texture * | |
239 SW_ActivateRenderer(SDL_Renderer * renderer) | |
240 { | |
241 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
242 SDL_Window *window = renderer->window; | |
243 | |
244 if (data->updateSize) { | |
245 /* Recreate the textures for the new window size */ | |
246 if (data->texture) { | |
247 DestroyTexture(data->renderer, data->texture); | |
248 } | |
249 data->texture = CreateTexture(data->renderer, data->format, | |
250 window->w, window->h); | |
251 if (data->texture) { | |
252 data->updateSize = SDL_FALSE; | |
253 } | |
254 } | |
255 return data->texture; | |
256 } | |
257 | |
258 static void | |
259 SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) | |
260 { | |
261 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
262 | |
263 if (event->event == SDL_WINDOWEVENT_RESIZED) { | |
264 data->updateSize = SDL_TRUE; | |
265 } | |
266 } | |
267 | |
268 static int | |
269 SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
270 { | |
271 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
272 texture->driverdata = | |
273 SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h); | |
274 } else { | |
275 int bpp; | |
276 Uint32 Rmask, Gmask, Bmask, Amask; | |
277 | |
278 if (!SDL_PixelFormatEnumToMasks | |
279 (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | |
280 SDL_SetError("Unknown texture format"); | |
281 return -1; | |
282 } | |
283 | |
284 texture->driverdata = | |
285 SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, | |
286 Bmask, Amask); | |
287 SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g, | |
288 texture->b); | |
289 SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a); | |
290 SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode); | |
291 | |
292 if (texture->access == SDL_TEXTUREACCESS_STATIC) { | |
293 SDL_SetSurfaceRLE(texture->driverdata, 1); | |
294 } | |
295 } | |
296 | |
297 if (!texture->driverdata) { | |
298 return -1; | |
299 } | |
300 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 } | |
319 | |
320 static int | |
321 SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) | |
322 { | |
323 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
324 return SDL_SetSurfaceColorMod(surface, texture->r, texture->g, | |
325 texture->b); | |
326 } | |
327 | |
328 static int | |
329 SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) | |
330 { | |
331 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
332 return SDL_SetSurfaceAlphaMod(surface, texture->a); | |
333 } | |
334 | |
335 static int | |
336 SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture) | |
337 { | |
338 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
339 return SDL_SetSurfaceBlendMode(surface, texture->blendMode); | |
340 } | |
341 | |
342 static int | |
343 SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
344 const SDL_Rect * rect, const void *pixels, int pitch) | |
345 { | |
346 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
347 return SDL_SW_UpdateYUVTexture((SDL_SW_YUVTexture *) | |
348 texture->driverdata, rect, pixels, | |
349 pitch); | |
350 } else { | |
351 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
352 Uint8 *src, *dst; | |
353 int row; | |
354 size_t length; | |
355 | |
356 src = (Uint8 *) pixels; | |
357 dst = | |
358 (Uint8 *) surface->pixels + rect->y * surface->pitch + | |
359 rect->x * surface->format->BytesPerPixel; | |
360 length = rect->w * surface->format->BytesPerPixel; | |
361 for (row = 0; row < rect->h; ++row) { | |
362 SDL_memcpy(dst, src, length); | |
363 src += pitch; | |
364 dst += surface->pitch; | |
365 } | |
366 return 0; | |
367 } | |
368 } | |
369 | |
370 static int | |
371 SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
372 const SDL_Rect * rect, int markDirty, void **pixels, | |
373 int *pitch) | |
374 { | |
375 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
376 return SDL_SW_LockYUVTexture((SDL_SW_YUVTexture *) | |
377 texture->driverdata, rect, markDirty, | |
378 pixels, pitch); | |
379 } else { | |
380 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
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 } | |
389 | |
390 static void | |
391 SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
392 { | |
393 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
394 SDL_SW_UnlockYUVTexture((SDL_SW_YUVTexture *) texture->driverdata); | |
395 } | |
396 } | |
397 | |
398 static int | |
399 SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, | |
400 int count) | |
401 { | |
402 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
403 SDL_Texture *texture = SW_ActivateRenderer(renderer); | |
404 SDL_Rect rect; | |
405 int i; | |
406 int x, y; | |
407 int status = 0; | |
408 | |
409 if (!texture) { | |
410 return -1; | |
411 } | |
412 | |
413 /* Get the smallest rectangle that contains everything */ | |
414 rect.x = 0; | |
415 rect.y = 0; | |
416 rect.w = texture->w; | |
417 rect.h = texture->h; | |
418 if (!SDL_EnclosePoints(points, count, &rect, &rect)) { | |
419 /* Nothing to draw */ | |
420 return 0; | |
421 } | |
422 | |
423 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, | |
424 &data->surface.pixels, | |
425 &data->surface.pitch) < 0) { | |
426 return -1; | |
427 } | |
428 | |
429 data->surface.clip_rect.w = data->surface.w = rect.w; | |
430 data->surface.clip_rect.h = data->surface.h = rect.h; | |
431 | |
432 /* Draw the points! */ | |
433 if (renderer->blendMode == SDL_BLENDMODE_NONE) { | |
434 Uint32 color = SDL_MapRGBA(data->surface.format, | |
435 renderer->r, renderer->g, renderer->b, | |
436 renderer->a); | |
437 | |
438 for (i = 0; i < count; ++i) { | |
439 x = points[i].x - rect.x; | |
440 y = points[i].y - rect.y; | |
441 | |
442 status = SDL_DrawPoint(&data->surface, x, y, color); | |
443 } | |
444 } else { | |
445 for (i = 0; i < count; ++i) { | |
446 x = points[i].x - rect.x; | |
447 y = points[i].y - rect.y; | |
448 | |
449 status = SDL_BlendPoint(&data->surface, x, y, | |
450 renderer->blendMode, | |
451 renderer->r, renderer->g, renderer->b, | |
452 renderer->a); | |
453 } | |
454 } | |
455 | |
456 data->renderer->UnlockTexture(data->renderer, texture); | |
457 | |
458 return status; | |
459 } | |
460 | |
461 static int | |
462 SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, | |
463 int count) | |
464 { | |
465 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
466 SDL_Texture *texture = SW_ActivateRenderer(renderer); | |
467 SDL_Rect clip, rect; | |
468 int i; | |
469 int x1, y1, x2, y2; | |
470 int status = 0; | |
471 | |
472 if (!texture) { | |
473 return -1; | |
474 } | |
475 | |
476 /* Get the smallest rectangle that contains everything */ | |
477 clip.x = 0; | |
478 clip.y = 0; | |
479 clip.w = texture->w; | |
480 clip.h = texture->h; | |
481 SDL_EnclosePoints(points, count, NULL, &rect); | |
482 if (!SDL_IntersectRect(&rect, &clip, &rect)) { | |
483 /* Nothing to draw */ | |
484 return 0; | |
485 } | |
486 | |
487 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, | |
488 &data->surface.pixels, | |
489 &data->surface.pitch) < 0) { | |
490 return -1; | |
491 } | |
492 | |
493 data->surface.clip_rect.w = data->surface.w = rect.w; | |
494 data->surface.clip_rect.h = data->surface.h = rect.h; | |
495 | |
496 /* Draw the points! */ | |
497 if (renderer->blendMode == SDL_BLENDMODE_NONE) { | |
498 Uint32 color = SDL_MapRGBA(data->surface.format, | |
499 renderer->r, renderer->g, renderer->b, | |
500 renderer->a); | |
501 | |
502 for (i = 1; i < count; ++i) { | |
503 x1 = points[i-1].x - rect.x; | |
504 y1 = points[i-1].y - rect.y; | |
505 x2 = points[i].x - rect.x; | |
506 y2 = points[i].y - rect.y; | |
507 | |
508 status = SDL_DrawLine(&data->surface, x1, y1, x2, y2, color); | |
509 } | |
510 } else { | |
511 for (i = 1; i < count; ++i) { | |
512 x1 = points[i-1].x - rect.x; | |
513 y1 = points[i-1].y - rect.y; | |
514 x2 = points[i].x - rect.x; | |
515 y2 = points[i].y - rect.y; | |
516 | |
517 status = SDL_BlendLine(&data->surface, x1, y1, x2, y2, | |
518 renderer->blendMode, | |
519 renderer->r, renderer->g, renderer->b, | |
520 renderer->a); | |
521 } | |
522 } | |
523 | |
524 data->renderer->UnlockTexture(data->renderer, texture); | |
525 | |
526 return status; | |
527 } | |
528 | |
529 static int | |
530 SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, | |
531 int count) | |
532 { | |
533 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
534 SDL_Texture *texture = SW_ActivateRenderer(renderer); | |
535 SDL_Rect clip, rect; | |
536 Uint32 color = 0; | |
537 int i; | |
538 int status = 0; | |
539 | |
540 if (!texture) { | |
541 return -1; | |
542 } | |
543 | |
544 clip.x = 0; | |
545 clip.y = 0; | |
546 clip.w = texture->w; | |
547 clip.h = texture->h; | |
548 | |
549 if (renderer->blendMode == SDL_BLENDMODE_NONE) { | |
550 color = SDL_MapRGBA(data->surface.format, | |
551 renderer->r, renderer->g, renderer->b, | |
552 renderer->a); | |
553 } | |
554 | |
555 for (i = 0; i < count; ++i) { | |
556 if (!SDL_IntersectRect(rects[i], &clip, &rect)) { | |
557 /* Nothing to draw */ | |
558 continue; | |
559 } | |
560 | |
561 if (data->renderer->LockTexture(data->renderer, texture, &rect, 1, | |
562 &data->surface.pixels, | |
563 &data->surface.pitch) < 0) { | |
564 return -1; | |
565 } | |
566 | |
567 data->surface.clip_rect.w = data->surface.w = rect.w; | |
568 data->surface.clip_rect.h = data->surface.h = rect.h; | |
569 | |
570 if (renderer->blendMode == SDL_BLENDMODE_NONE) { | |
571 status = SDL_FillRect(&data->surface, NULL, color); | |
572 } else { | |
573 status = SDL_BlendFillRect(&data->surface, NULL, | |
574 renderer->blendMode, | |
575 renderer->r, renderer->g, renderer->b, | |
576 renderer->a); | |
577 } | |
578 | |
579 data->renderer->UnlockTexture(data->renderer, texture); | |
580 } | |
581 return status; | |
582 } | |
583 | |
584 static int | |
585 SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
586 const SDL_Rect * srcrect, const SDL_Rect * dstrect) | |
587 { | |
588 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
589 int status; | |
590 | |
591 if (!SW_ActivateRenderer(renderer)) { | |
592 return -1; | |
593 } | |
594 | |
595 if (data->renderer->LockTexture(data->renderer, data->texture, | |
596 dstrect, 1, &data->surface.pixels, | |
597 &data->surface.pitch) < 0) { | |
598 return -1; | |
599 } | |
600 | |
601 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
602 status = | |
603 SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata, | |
604 srcrect, data->format, dstrect->w, dstrect->h, | |
605 data->surface.pixels, data->surface.pitch); | |
606 } else { | |
607 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
608 SDL_Rect real_srcrect = *srcrect; | |
609 SDL_Rect real_dstrect; | |
610 | |
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); | |
622 return status; | |
623 } | |
624 | |
625 static int | |
626 SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, | |
627 Uint32 format, void * pixels, int pitch) | |
628 { | |
629 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
630 | |
631 if (!SW_ActivateRenderer(renderer)) { | |
632 return -1; | |
633 } | |
634 | |
635 if (data->renderer->LockTexture(data->renderer, data->texture, | |
636 rect, 0, &data->surface.pixels, | |
637 &data->surface.pitch) < 0) { | |
638 return -1; | |
639 } | |
640 | |
641 SDL_ConvertPixels(rect->w, rect->h, | |
642 data->format, data->surface.pixels, data->surface.pitch, | |
643 format, pixels, pitch); | |
644 | |
645 data->renderer->UnlockTexture(data->renderer, data->texture); | |
646 return 0; | |
647 } | |
648 | |
649 static int | |
650 SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect, | |
651 Uint32 format, const void * pixels, int pitch) | |
652 { | |
653 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
654 | |
655 if (!SW_ActivateRenderer(renderer)) { | |
656 return -1; | |
657 } | |
658 | |
659 if (data->renderer->LockTexture(data->renderer, data->texture, | |
660 rect, 1, &data->surface.pixels, | |
661 &data->surface.pitch) < 0) { | |
662 return -1; | |
663 } | |
664 | |
665 SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch, | |
666 data->format, data->surface.pixels, data->surface.pitch); | |
667 | |
668 data->renderer->UnlockTexture(data->renderer, data->texture); | |
669 return 0; | |
670 } | |
671 | |
672 static void | |
673 SW_RenderPresent(SDL_Renderer * renderer) | |
674 { | |
675 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
676 SDL_Texture *texture = SW_ActivateRenderer(renderer); | |
677 SDL_Rect rect; | |
678 | |
679 if (!texture) { | |
680 return; | |
681 } | |
682 | |
683 /* Send the data to the display */ | |
684 rect.x = 0; | |
685 rect.y = 0; | |
686 rect.w = texture->w; | |
687 rect.h = texture->h; | |
688 data->renderer->RenderCopy(data->renderer, texture, &rect, &rect); | |
689 data->renderer->RenderPresent(data->renderer); | |
690 } | |
691 | |
692 static void | |
693 SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
694 { | |
695 if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { | |
696 SDL_SW_DestroyYUVTexture((SDL_SW_YUVTexture *) texture->driverdata); | |
697 } else { | |
698 SDL_Surface *surface = (SDL_Surface *) texture->driverdata; | |
699 | |
700 SDL_FreeSurface(surface); | |
701 } | |
702 } | |
703 | |
704 static void | |
705 SW_DestroyRenderer(SDL_Renderer * renderer) | |
706 { | |
707 SW_RenderData *data = (SW_RenderData *) renderer->driverdata; | |
708 SDL_Window *window = renderer->window; | |
709 | |
710 if (data) { | |
711 if (data->texture) { | |
712 DestroyTexture(data->renderer, data->texture); | |
713 } | |
714 if (data->surface.format) { | |
715 SDL_FreeFormat(data->surface.format); | |
716 } | |
717 if (data->renderer) { | |
718 data->renderer->DestroyRenderer(data->renderer); | |
719 } | |
720 SDL_FreeDirtyRects(&data->dirty); | |
721 SDL_free(data); | |
722 } | |
723 SDL_free(renderer); | |
724 } | |
725 | |
726 /* vi: set ts=4 sw=4 expandtab: */ |