Mercurial > sdl-ios-xcode
comparison src/render/SDL_render.c @ 5161:b3ccd1947786
Simplified and improved the process of creating a texture from a surface.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 03 Feb 2011 00:54:29 -0800 |
parents | 657543cc92f9 |
children | 4d39eeaad00b |
comparison
equal
deleted
inserted
replaced
5160:657543cc92f9 | 5161:b3ccd1947786 |
---|---|
248 } | 248 } |
249 return texture; | 249 return texture; |
250 } | 250 } |
251 | 251 |
252 SDL_Texture * | 252 SDL_Texture * |
253 SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface) | 253 SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface) |
254 { | 254 { |
255 SDL_Texture *texture; | 255 const SDL_PixelFormat *fmt; |
256 Uint32 requested_format = format; | 256 SDL_bool needAlpha; |
257 SDL_PixelFormat *fmt; | 257 Uint32 i; |
258 Uint32 format; | |
258 int bpp; | 259 int bpp; |
259 Uint32 Rmask, Gmask, Bmask, Amask; | 260 Uint32 Rmask, Gmask, Bmask, Amask; |
261 SDL_Texture *texture; | |
260 | 262 |
261 CHECK_RENDERER_MAGIC(renderer, NULL); | 263 CHECK_RENDERER_MAGIC(renderer, NULL); |
262 | 264 |
263 if (!surface) { | 265 if (!surface) { |
264 SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); | 266 SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); |
265 return NULL; | 267 return NULL; |
266 } | 268 } |
269 | |
270 /* See what the best texture format is */ | |
267 fmt = surface->format; | 271 fmt = surface->format; |
268 | 272 if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) { |
269 if (format) { | 273 needAlpha = SDL_TRUE; |
270 if (!SDL_PixelFormatEnumToMasks | 274 } else { |
271 (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { | 275 needAlpha = SDL_FALSE; |
272 SDL_SetError("Unknown pixel format"); | 276 } |
273 return 0; | 277 format = renderer->info.texture_formats[0]; |
274 } | 278 for (i = 0; i < renderer->info.num_texture_formats; ++i) { |
275 } else { | 279 if (SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) { |
276 SDL_bool hasColorkey; | 280 format = renderer->info.texture_formats[i]; |
277 SDL_BlendMode blendMode; | 281 break; |
278 SDL_bool hasBlending; | 282 } |
279 | 283 } |
280 hasColorkey = (SDL_GetColorKey(surface, NULL) == 0); | 284 |
281 | 285 if (!SDL_PixelFormatEnumToMasks(format, &bpp, |
282 SDL_GetSurfaceBlendMode(surface, &blendMode); | 286 &Rmask, &Gmask, &Bmask, &Amask)) { |
283 hasBlending = (blendMode == SDL_BLENDMODE_BLEND); | 287 SDL_SetError("Unknown pixel format"); |
284 | 288 return NULL; |
285 if (surface->format->Amask || (!hasColorkey && !hasBlending)) { | 289 } |
286 Uint32 it; | 290 |
287 int pfmt; | 291 texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, |
288 | 292 surface->w, surface->h); |
289 /* Pixel formats, sorted by best first */ | |
290 static const Uint32 sdl_pformats[] = { | |
291 SDL_PIXELFORMAT_ARGB8888, | |
292 SDL_PIXELFORMAT_RGBA8888, | |
293 SDL_PIXELFORMAT_ABGR8888, | |
294 SDL_PIXELFORMAT_BGRA8888, | |
295 SDL_PIXELFORMAT_RGB888, | |
296 SDL_PIXELFORMAT_BGR888, | |
297 SDL_PIXELFORMAT_RGB24, | |
298 SDL_PIXELFORMAT_BGR24, | |
299 SDL_PIXELFORMAT_RGB565, | |
300 SDL_PIXELFORMAT_BGR565, | |
301 SDL_PIXELFORMAT_ARGB1555, | |
302 SDL_PIXELFORMAT_RGBA5551, | |
303 SDL_PIXELFORMAT_ABGR1555, | |
304 SDL_PIXELFORMAT_BGRA5551, | |
305 SDL_PIXELFORMAT_RGB555, | |
306 SDL_PIXELFORMAT_BGR555, | |
307 SDL_PIXELFORMAT_ARGB4444, | |
308 SDL_PIXELFORMAT_RGBA4444, | |
309 SDL_PIXELFORMAT_ABGR4444, | |
310 SDL_PIXELFORMAT_BGRA4444, | |
311 SDL_PIXELFORMAT_RGB444, | |
312 SDL_PIXELFORMAT_ARGB2101010, | |
313 SDL_PIXELFORMAT_RGB332, | |
314 SDL_PIXELFORMAT_UNKNOWN | |
315 }; | |
316 | |
317 bpp = fmt->BitsPerPixel; | |
318 Rmask = fmt->Rmask; | |
319 Gmask = fmt->Gmask; | |
320 Bmask = fmt->Bmask; | |
321 Amask = fmt->Amask; | |
322 | |
323 format = | |
324 SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask); | |
325 if (!format) { | |
326 SDL_SetError("Unknown pixel format"); | |
327 return 0; | |
328 } | |
329 | |
330 /* Search requested format in the supported texture */ | |
331 /* formats by current renderer */ | |
332 for (it = 0; it < renderer->info.num_texture_formats; it++) { | |
333 if (renderer->info.texture_formats[it] == format) { | |
334 break; | |
335 } | |
336 } | |
337 | |
338 /* If requested format can't be found, search any best */ | |
339 /* format which renderer provides */ | |
340 if (it == renderer->info.num_texture_formats) { | |
341 pfmt = 0; | |
342 for (;;) { | |
343 if (sdl_pformats[pfmt] == SDL_PIXELFORMAT_UNKNOWN) { | |
344 break; | |
345 } | |
346 | |
347 for (it = 0; it < renderer->info.num_texture_formats; | |
348 it++) { | |
349 if (renderer->info.texture_formats[it] == | |
350 sdl_pformats[pfmt]) { | |
351 break; | |
352 } | |
353 } | |
354 | |
355 if (it != renderer->info.num_texture_formats) { | |
356 /* The best format has been found */ | |
357 break; | |
358 } | |
359 pfmt++; | |
360 } | |
361 | |
362 /* If any format can't be found, then return an error */ | |
363 if (it == renderer->info.num_texture_formats) { | |
364 SDL_SetError | |
365 ("Any of the supported pixel formats can't be found"); | |
366 return 0; | |
367 } | |
368 | |
369 /* Convert found pixel format back to color masks */ | |
370 if (SDL_PixelFormatEnumToMasks | |
371 (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask, | |
372 &Bmask, &Amask) != SDL_TRUE) { | |
373 SDL_SetError("Unknown pixel format"); | |
374 return 0; | |
375 } | |
376 } | |
377 } else { | |
378 /* Need a format with alpha */ | |
379 Uint32 it; | |
380 int apfmt; | |
381 | |
382 /* Pixel formats with alpha, sorted by best first */ | |
383 static const Uint32 sdl_alpha_pformats[] = { | |
384 SDL_PIXELFORMAT_ARGB8888, | |
385 SDL_PIXELFORMAT_RGBA8888, | |
386 SDL_PIXELFORMAT_ABGR8888, | |
387 SDL_PIXELFORMAT_BGRA8888, | |
388 SDL_PIXELFORMAT_ARGB1555, | |
389 SDL_PIXELFORMAT_RGBA5551, | |
390 SDL_PIXELFORMAT_ABGR1555, | |
391 SDL_PIXELFORMAT_BGRA5551, | |
392 SDL_PIXELFORMAT_ARGB4444, | |
393 SDL_PIXELFORMAT_RGBA4444, | |
394 SDL_PIXELFORMAT_ABGR4444, | |
395 SDL_PIXELFORMAT_BGRA4444, | |
396 SDL_PIXELFORMAT_ARGB2101010, | |
397 SDL_PIXELFORMAT_UNKNOWN | |
398 }; | |
399 | |
400 if (surface->format->Amask) { | |
401 /* If surface already has alpha, then try an original */ | |
402 /* surface format first */ | |
403 bpp = fmt->BitsPerPixel; | |
404 Rmask = fmt->Rmask; | |
405 Gmask = fmt->Gmask; | |
406 Bmask = fmt->Bmask; | |
407 Amask = fmt->Amask; | |
408 } else { | |
409 bpp = 32; | |
410 Rmask = 0x00FF0000; | |
411 Gmask = 0x0000FF00; | |
412 Bmask = 0x000000FF; | |
413 Amask = 0xFF000000; | |
414 } | |
415 | |
416 format = | |
417 SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask); | |
418 if (!format) { | |
419 SDL_SetError("Unknown pixel format"); | |
420 return 0; | |
421 } | |
422 | |
423 /* Search this format in the supported texture formats */ | |
424 /* by current renderer */ | |
425 for (it = 0; it < renderer->info.num_texture_formats; it++) { | |
426 if (renderer->info.texture_formats[it] == format) { | |
427 break; | |
428 } | |
429 } | |
430 | |
431 /* If this format can't be found, search any best */ | |
432 /* compatible format with alpha which renderer provides */ | |
433 if (it == renderer->info.num_texture_formats) { | |
434 apfmt = 0; | |
435 for (;;) { | |
436 if (sdl_alpha_pformats[apfmt] == SDL_PIXELFORMAT_UNKNOWN) { | |
437 break; | |
438 } | |
439 | |
440 for (it = 0; it < renderer->info.num_texture_formats; | |
441 it++) { | |
442 if (renderer->info.texture_formats[it] == | |
443 sdl_alpha_pformats[apfmt]) { | |
444 break; | |
445 } | |
446 } | |
447 | |
448 if (it != renderer->info.num_texture_formats) { | |
449 /* Compatible format has been found */ | |
450 break; | |
451 } | |
452 apfmt++; | |
453 } | |
454 | |
455 /* If compatible format can't be found, then return an error */ | |
456 if (it == renderer->info.num_texture_formats) { | |
457 SDL_SetError("Compatible pixel format can't be found"); | |
458 return 0; | |
459 } | |
460 | |
461 /* Convert found pixel format back to color masks */ | |
462 if (SDL_PixelFormatEnumToMasks | |
463 (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask, | |
464 &Bmask, &Amask) != SDL_TRUE) { | |
465 SDL_SetError("Unknown pixel format"); | |
466 return 0; | |
467 } | |
468 } | |
469 } | |
470 | |
471 format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask); | |
472 if (!format) { | |
473 SDL_SetError("Unknown pixel format"); | |
474 return 0; | |
475 } | |
476 } | |
477 | |
478 texture = | |
479 SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, | |
480 surface->w, surface->h); | |
481 if (!texture && !requested_format) { | |
482 SDL_DisplayMode desktop_mode; | |
483 SDL_GetDesktopDisplayMode(&desktop_mode); | |
484 format = desktop_mode.format; | |
485 texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, | |
486 surface->w, surface->h); | |
487 } | |
488 if (!texture) { | 293 if (!texture) { |
489 return 0; | 294 return NULL; |
490 } | 295 } |
296 | |
491 if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask | 297 if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask |
492 && Bmask == fmt->Bmask && Amask == fmt->Amask) { | 298 && Bmask == fmt->Bmask && Amask == fmt->Amask) { |
493 if (SDL_MUSTLOCK(surface)) { | 299 if (SDL_MUSTLOCK(surface)) { |
494 SDL_LockSurface(surface); | 300 SDL_LockSurface(surface); |
495 SDL_UpdateTexture(texture, NULL, surface->pixels, | 301 SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch); |
496 surface->pitch); | |
497 SDL_UnlockSurface(surface); | 302 SDL_UnlockSurface(surface); |
498 } else { | 303 } else { |
499 SDL_UpdateTexture(texture, NULL, surface->pixels, | 304 SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch); |
500 surface->pitch); | |
501 } | 305 } |
502 } else { | 306 } else { |
503 SDL_PixelFormat dst_fmt; | 307 SDL_PixelFormat dst_fmt; |
504 SDL_Surface *dst = NULL; | 308 SDL_Surface *temp = NULL; |
505 | 309 |
506 /* Set up a destination surface for the texture update */ | 310 /* Set up a destination surface for the texture update */ |
507 SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask); | 311 SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask); |
508 dst = SDL_ConvertSurface(surface, &dst_fmt, 0); | 312 temp = SDL_ConvertSurface(surface, &dst_fmt, 0); |
509 if (dst) { | 313 if (temp) { |
510 SDL_UpdateTexture(texture, NULL, dst->pixels, dst->pitch); | 314 SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch); |
511 SDL_FreeSurface(dst); | 315 SDL_FreeSurface(temp); |
512 } | 316 } else { |
513 if (!dst) { | |
514 SDL_DestroyTexture(texture); | 317 SDL_DestroyTexture(texture); |
515 return 0; | 318 return NULL; |
516 } | 319 } |
517 } | 320 } |
518 | 321 |
519 { | 322 { |
520 Uint8 r, g, b, a; | 323 Uint8 r, g, b, a; |