SDL: Use pixman for software scaling
Jeffrey Pfau jeffrey@endrift.com
Wed, 18 Mar 2015 01:39:20 -0700
3 files changed,
56 insertions(+),
6 deletions(-)
M
src/platform/sdl/CMakeLists.txt
→
src/platform/sdl/CMakeLists.txt
@@ -17,6 +17,7 @@ if(SDL_VERSION EQUAL "1.2" OR NOT SDL2_FOUND)
find_package(SDL 1.2) set(SDL_VERSION "1.2" PARENT_SCOPE) set(SDL_VERSION_DEBIAN "1.2debian") + set(USE_PIXMAN ON) endif() if (NOT SDL2_FOUND AND NOT SDL_FOUND)@@ -24,10 +25,16 @@ set(BUILD_SDL OFF PARENT_SCOPE)
return() endif() +find_feature(USE_PIXMAN "pixman-1") +if(USE_PIXMAN) + add_definitions(-DUSE_PIXMAN) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libpixman-1.0" PARENT_SCOPE) +endif() + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libsdl${SDL_VERSION_DEBIAN}" PARENT_SCOPE) file(GLOB PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sdl-*.c) -set(PLATFORM_LIBRARY ${SDL_LIBRARY} ${SDLMAIN_LIBRARY}) +set(PLATFORM_LIBRARY ${SDL_LIBRARY} ${SDLMAIN_LIBRARY} ${PIXMAN-1_LIBRARIES}) include_directories(${CMAKE_SOURCE_DIR}/src/platform/sdl ${SDL_INCLUDE_DIR}) set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/main.c)
M
src/platform/sdl/main.h
→
src/platform/sdl/main.h
@@ -31,6 +31,10 @@ #include <bcm_host.h>
#pragma GCC diagnostic pop #endif +#ifdef USE_PIXMAN +#include <pixman.h> +#endif + struct SDLSoftwareRenderer { struct GBAVideoSoftwareRenderer d; struct GBASDLAudio audio;@@ -53,6 +57,11 @@ bool filter;
#ifdef BUILD_GL GLuint tex; +#endif + +#ifdef USE_PIXMAN + pixman_image_t* pix; + pixman_image_t* screenpix; #endif #ifdef BUILD_RASPI
M
src/platform/sdl/sw-sdl.c
→
src/platform/sdl/sw-sdl.c
@@ -40,14 +40,32 @@ SDL_LockSurface(surface);
if (renderer->ratio == 1) { renderer->d.outputBuffer = surface->pixels; + renderer->d.outputBufferStride = surface->pitch / BYTES_PER_PIXEL; + } else { +#ifdef USE_PIXMAN + renderer->d.outputBuffer = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL); + renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS; #ifdef COLOR_16_BIT - renderer->d.outputBufferStride = surface->pitch / 2; +#ifdef COLOR_5_6_5 + pixman_format_code_t format = PIXMAN_r5g6b5; #else - renderer->d.outputBufferStride = surface->pitch / 4; + pixman_format_code_t format = PIXMAN_x1b5g5r5; #endif - } else { - renderer->d.outputBuffer = malloc(240 * 160 * BYTES_PER_PIXEL); - renderer->d.outputBufferStride = 240; +#else + pixman_format_code_t format = PIXMAN_x8b8g8r8; +#endif + renderer->pix = pixman_image_create_bits(format, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, + renderer->d.outputBuffer, renderer->d.outputBufferStride * BYTES_PER_PIXEL); + renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch); + + pixman_transform_t transform; + pixman_transform_init_identity(&transform); + pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio)); + pixman_image_set_transform(renderer->pix, &transform); + pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0); +#else + return false; +#endif } #endif@@ -73,6 +91,13 @@ SDL_RenderPresent(renderer->sdlRenderer);
SDL_LockTexture(renderer->tex, 0, (void**) &renderer->d.outputBuffer, &renderer->d.outputBufferStride); renderer->d.outputBufferStride /= BYTES_PER_PIXEL; #else +#ifdef USE_PIXMAN + if (renderer->ratio > 1) { + pixman_image_composite32(PIXMAN_OP_SRC, renderer->pix, 0, renderer->screenpix, + 0, 0, 0, 0, 0, 0, + renderer->viewportWidth, renderer->viewportHeight); + } +#else switch (renderer->ratio) { #if defined(__ARM_NEON) && COLOR_16_BIT case 2:@@ -87,6 +112,7 @@ break;
default: abort(); } +#endif SDL_UnlockSurface(surface); SDL_Flip(surface); SDL_LockSurface(surface);@@ -98,4 +124,12 @@ }
void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) { UNUSED(renderer); +#if !SDL_VERSION_ATLEAST(2, 0, 0) + SDL_Surface* surface = SDL_GetVideoSurface(); + SDL_UnlockSurface(surface); +#ifdef USE_PIXMAN + pixman_image_unref(renderer->pix); + pixman_image_unref(renderer->screenpix); +#endif +#endif }