mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 10:25:46 +01:00 
			
		
		
		
	Switch code to SDL2.
Also simplify wasm html (now that it is suppported by all browsers). Change-Id: I352b08594b93d3dd7d44832d4328b3546ccc1b90
This commit is contained in:
		| @@ -638,13 +638,13 @@ if(WEBP_BUILD_EXTRAS) | ||||
|                                                   ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|  | ||||
|   # vwebp_sdl | ||||
|   find_package(SDL) | ||||
|   if(WEBP_BUILD_VWEBP AND SDL_FOUND) | ||||
|   find_package(SDL2 QUIET) | ||||
|   if(WEBP_BUILD_VWEBP AND SDL2_FOUND) | ||||
|     add_executable(vwebp_sdl ${VWEBP_SDL_SRCS}) | ||||
|     target_link_libraries(vwebp_sdl ${SDL_LIBRARY} imageioutil webp) | ||||
|     target_link_libraries(vwebp_sdl ${SDL2_LIBRARIES} imageioutil webp) | ||||
|     target_include_directories( | ||||
|       vwebp_sdl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} | ||||
|                         ${CMAKE_CURRENT_BINARY_DIR}/src ${SDL_INCLUDE_DIR}) | ||||
|                         ${CMAKE_CURRENT_BINARY_DIR}/src ${SDL2_INCLUDE_DIRS}) | ||||
|     set(WEBP_HAVE_SDL 1) | ||||
|     target_compile_definitions(vwebp_sdl PUBLIC WEBP_HAVE_SDL) | ||||
|   endif() | ||||
| @@ -661,31 +661,43 @@ if(WEBP_BUILD_WEBP_JS) | ||||
|   else() | ||||
|     set(emscripten_stack_size "-sTOTAL_STACK=5MB") | ||||
|   endif() | ||||
|   # Set SDL2 flags so that ports are downloaded by emscripten. | ||||
|   set(EMSCRIPTEN_SDL2_FLAGS "-sUSE_SDL=2 -sUSE_SDL_IMAGE=2") | ||||
|   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EMSCRIPTEN_SDL2_FLAGS}") | ||||
|   # wasm2js does not support SIMD. | ||||
|   if(NOT WEBP_ENABLE_SIMD) | ||||
|     # JavaScript version | ||||
|     find_package(SDL2 QUIET) | ||||
|     add_executable(webp_js ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c) | ||||
|     target_link_libraries(webp_js webpdecoder SDL) | ||||
|     target_link_libraries(webp_js webpdecoder SDL2) | ||||
|     target_include_directories(webp_js PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|     set(WEBP_HAVE_SDL 1) | ||||
|     set_target_properties( | ||||
|       webp_js | ||||
|       PROPERTIES LINK_FLAGS "-sWASM=0 ${emscripten_stack_size} \ | ||||
|       PROPERTIES | ||||
|         LINK_FLAGS | ||||
|         "-sWASM=0 ${emscripten_stack_size} \ | ||||
|          -sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \ | ||||
|          -sEXPORTED_RUNTIME_METHODS=cwrap") | ||||
|          -sEXPORTED_RUNTIME_METHODS=cwrap ${EMSCRIPTEN_SDL2_FLAGS} \ | ||||
|          -sALLOW_MEMORY_GROWTH" | ||||
|     ) | ||||
|     set_target_properties(webp_js PROPERTIES OUTPUT_NAME webp) | ||||
|     target_compile_definitions(webp_js PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) | ||||
|   endif() | ||||
|  | ||||
|   # WASM version | ||||
|   add_executable(webp_wasm ${CMAKE_CURRENT_SOURCE_DIR}/extras/webp_to_sdl.c) | ||||
|   target_link_libraries(webp_wasm webpdecoder SDL) | ||||
|   target_link_libraries(webp_wasm webpdecoder SDL2) | ||||
|   target_include_directories(webp_wasm PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) | ||||
|   set_target_properties( | ||||
|     webp_wasm | ||||
|     PROPERTIES LINK_FLAGS "-sWASM=1 ${emscripten_stack_size} \ | ||||
|     PROPERTIES | ||||
|       LINK_FLAGS | ||||
|       "-sWASM=1 ${emscripten_stack_size} \ | ||||
|        -sEXPORTED_FUNCTIONS=_WebPToSDL -sINVOKE_RUN=0 \ | ||||
|        -sEXPORTED_RUNTIME_METHODS=cwrap") | ||||
|        -sEXPORTED_RUNTIME_METHODS=cwrap ${EMSCRIPTEN_SDL2_FLAGS} \ | ||||
|        -sALLOW_MEMORY_GROWTH" | ||||
|   ) | ||||
|   target_compile_definitions(webp_wasm PUBLIC EMSCRIPTEN WEBP_HAVE_SDL) | ||||
|  | ||||
|   target_compile_definitions(webpdspdecode PUBLIC EMSCRIPTEN) | ||||
|   | ||||
| @@ -464,7 +464,7 @@ AC_ARG_ENABLE([sdl], | ||||
|                               @<:@default=auto@:>@])) | ||||
| AS_IF([test "x$enable_sdl" != "xno"], [ | ||||
|   CLEAR_LIBVARS([SDL]) | ||||
|   AC_PATH_PROGS([LIBSDL_CONFIG], [sdl-config]) | ||||
|   AC_PATH_PROGS([LIBSDL_CONFIG], [sdl2-config]) | ||||
|   if test -n "$LIBSDL_CONFIG"; then | ||||
|     SDL_INCLUDES=`$LIBSDL_CONFIG --cflags` | ||||
|     SDL_LIBS="`$LIBSDL_CONFIG --libs`" | ||||
| @@ -474,13 +474,12 @@ AS_IF([test "x$enable_sdl" != "xno"], [ | ||||
|  | ||||
|   sdl_header="no" | ||||
|   LIBCHECK_PROLOGUE([SDL]) | ||||
|   AC_CHECK_HEADER([SDL/SDL.h], [sdl_header="SDL/SDL.h"], | ||||
|                   [AC_CHECK_HEADER([SDL.h], [sdl_header="SDL.h"], | ||||
|                   [AC_MSG_WARN(SDL library not available - no sdl.h)])]) | ||||
|   AC_CHECK_HEADER([SDL2/SDL.h], [sdl_header="SDL2/SDL.h"], | ||||
|                   [AC_MSG_WARN(SDL2 library not available - no SDL.h)]) | ||||
|   if test x"$sdl_header" != "xno"; then | ||||
|     AC_LANG_PUSH(C) | ||||
|     SDL_SAVED_LIBS="$LIBS" | ||||
|     for lib in "" "-lSDL" "-lSDLmain -lSDL"; do | ||||
|     for lib in "" "-lSDL2" "-lSDL2main -lSDL2"; do | ||||
|       LIBS="$SDL_SAVED_LIBS $lib" | ||||
|       # Perform a full link to ensure SDL_main is resolved if needed. | ||||
|       AC_LINK_IFELSE( | ||||
|   | ||||
| @@ -30,7 +30,7 @@ | ||||
| #if defined(WEBP_HAVE_JUST_SDL_H) | ||||
| #include <SDL.h> | ||||
| #else | ||||
| #include <SDL/SDL.h> | ||||
| #include <SDL2/SDL.h> | ||||
| #endif | ||||
|  | ||||
| static void ProcessEvents(void) { | ||||
|   | ||||
| @@ -20,88 +20,75 @@ | ||||
| #include "webp_to_sdl.h" | ||||
|  | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "src/webp/decode.h" | ||||
|  | ||||
| #if defined(WEBP_HAVE_JUST_SDL_H) | ||||
| #include <SDL.h> | ||||
| #else | ||||
| #include <SDL/SDL.h> | ||||
| #include <SDL2/SDL.h> | ||||
| #endif | ||||
|  | ||||
| static int init_ok = 0; | ||||
| int WebPToSDL(const char* data, unsigned int data_size) { | ||||
|   int ok = 0; | ||||
|   VP8StatusCode status; | ||||
|   WebPDecoderConfig config; | ||||
|   WebPBitstreamFeatures* const input = &config.input; | ||||
|   WebPDecBuffer* const output = &config.output; | ||||
|   SDL_Surface* screen = NULL; | ||||
|   SDL_Surface* surface = NULL; | ||||
|  | ||||
|   if (!WebPInitDecoderConfig(&config)) { | ||||
|     fprintf(stderr, "Library version mismatch!\n"); | ||||
|     return 0; | ||||
|   } | ||||
|   WebPBitstreamFeatures input; | ||||
|   uint8_t* output = NULL; | ||||
|   SDL_Window* window = NULL; | ||||
|   SDL_Renderer* renderer = NULL; | ||||
|   SDL_Texture* texture = NULL; | ||||
|   int width, height; | ||||
|  | ||||
|   if (!init_ok) { | ||||
|     SDL_Init(SDL_INIT_VIDEO); | ||||
|     init_ok = 1; | ||||
|   } | ||||
|  | ||||
|   status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &config.input); | ||||
|   status = WebPGetFeatures((uint8_t*)data, (size_t)data_size, &input); | ||||
|   if (status != VP8_STATUS_OK) goto Error; | ||||
|   width = input.width; | ||||
|   height = input.height; | ||||
|  | ||||
|   screen = SDL_SetVideoMode(input->width, input->height, 32, SDL_SWSURFACE); | ||||
|   if (screen == NULL) { | ||||
|     fprintf(stderr, "Unable to set video mode (32bpp %dx%d)!\n", | ||||
|             input->width, input->height); | ||||
|   SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer); | ||||
|   if (window == NULL || renderer == NULL) { | ||||
|     fprintf(stderr, "Unable to create window or renderer!\n"); | ||||
|     goto Error; | ||||
|   } | ||||
|   SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, | ||||
|               "linear");  // make the scaled rendering look smoother. | ||||
|   SDL_RenderSetLogicalSize(renderer, width, height); | ||||
|  | ||||
|   surface = SDL_CreateRGBSurface(SDL_SWSURFACE, | ||||
|                                  input->width, input->height, 32, | ||||
|                                  0x000000ffu,   // R mask | ||||
|                                  0x0000ff00u,   // G mask | ||||
|                                  0x00ff0000u,   // B mask | ||||
|                                  0xff000000u);  // A mask | ||||
|  | ||||
|   if (surface == NULL) { | ||||
|     fprintf(stderr, "Unable to create %dx%d RGBA surface!\n", | ||||
|             input->width, input->height); | ||||
|   texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888, | ||||
|                               SDL_TEXTUREACCESS_STREAMING, width, height); | ||||
|   if (texture == NULL) { | ||||
|     fprintf(stderr, "Unable to create %dx%d RGBA texture!\n", width, height); | ||||
|     goto Error; | ||||
|   } | ||||
|   if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); | ||||
|  | ||||
| #if SDL_BYTEORDER == SDL_BIG_ENDIAN | ||||
|   output->colorspace = MODE_BGRA; | ||||
|   output = WebPDecodeBGRA((const uint8_t*)data, (size_t)data_size, &width, | ||||
|                           &height); | ||||
| #else | ||||
|   output->colorspace = MODE_RGBA; | ||||
|   output = WebPDecodeRGBA((const uint8_t*)data, (size_t)data_size, &width, | ||||
|                           &height); | ||||
| #endif | ||||
|   output->width  = surface->w; | ||||
|   output->height = surface->h; | ||||
|   output->u.RGBA.rgba   = surface->pixels; | ||||
|   output->u.RGBA.stride = surface->pitch; | ||||
|   output->u.RGBA.size   = surface->pitch * surface->h; | ||||
|   output->is_external_memory = 1; | ||||
|  | ||||
|   status = WebPDecode((const uint8_t*)data, (size_t)data_size, &config); | ||||
|   if (status != VP8_STATUS_OK) { | ||||
|   if (output == NULL) { | ||||
|     fprintf(stderr, "Error decoding image (%d)\n", status); | ||||
|     goto Error; | ||||
|   } | ||||
|  | ||||
|   if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); | ||||
|   if (SDL_BlitSurface(surface, NULL, screen, NULL) || | ||||
|       SDL_Flip(screen)) { | ||||
|     goto Error; | ||||
|   } | ||||
|  | ||||
|   SDL_UpdateTexture(texture, NULL, output, width * sizeof(uint32_t)); | ||||
|   SDL_RenderClear(renderer); | ||||
|   SDL_RenderCopy(renderer, texture, NULL, NULL); | ||||
|   SDL_RenderPresent(renderer); | ||||
|   ok = 1; | ||||
|  | ||||
|  Error: | ||||
|   SDL_FreeSurface(surface); | ||||
|   SDL_FreeSurface(screen); | ||||
|   WebPFreeDecBuffer(output); | ||||
|   // We should call SDL_DestroyWindow(window) but that makes .js fail. | ||||
|   SDL_DestroyRenderer(renderer); | ||||
|   SDL_DestroyTexture(texture); | ||||
|   WebPFree(output); | ||||
|   return ok; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -37,13 +37,13 @@ else | ||||
| endif | ||||
|  | ||||
| # SDL flags: use sdl-config if it exists | ||||
| SDL_CONFIG = $(shell sdl-config --version 2> /dev/null) | ||||
| SDL_CONFIG = $(shell sdl2-config --version 2> /dev/null) | ||||
| ifneq ($(SDL_CONFIG),) | ||||
|   SDL_LIBS = $(shell sdl-config --libs) | ||||
|   SDL_FLAGS = $(shell sdl-config --cflags) | ||||
|   SDL_LIBS = $(shell sdl2-config --libs) | ||||
|   SDL_FLAGS = $(shell sdl2-config --cflags) | ||||
| else | ||||
|   # use best-guess | ||||
|   SDL_LIBS = -lSDL | ||||
|   SDL_LIBS = -lSDL2 | ||||
|   SDL_FLAGS = | ||||
| endif | ||||
|  | ||||
|   | ||||
| @@ -20,8 +20,7 @@ Emscripten and CMake. | ||||
|  | ||||
|     ```shell | ||||
|     cd webp_js && \ | ||||
|     emcmake cmake -DWEBP_BUILD_WEBP_JS=ON \ | ||||
|           ../ | ||||
|     emcmake cmake -DWEBP_BUILD_WEBP_JS=ON ../ | ||||
|     ``` | ||||
|  | ||||
| -   compile webp.js using 'emmake make'. | ||||
| @@ -55,27 +54,7 @@ directory. | ||||
| See webp_js/index_wasm.html for a simple demo page using the WASM version of the | ||||
| library. | ||||
|  | ||||
| You will need a fairly recent version of Emscripten (at least 2.0.18, | ||||
| latest-upstream is recommended) and of your WASM-enabled browser to run this | ||||
| version. | ||||
|  | ||||
| ## Caveats | ||||
|  | ||||
| -   First decoding using the library is usually slower, due to just-in-time | ||||
|     compilation. | ||||
|  | ||||
| -   Some versions of llvm produce the following compile error when SSE2 is | ||||
|     enabled. | ||||
|  | ||||
|     ``` | ||||
|     "Unsupported:   %516 = bitcast <8 x i16> %481 to i128 | ||||
|     LLVM ERROR: BitCast Instruction not yet supported for integer types larger than 64 bits" | ||||
|     ``` | ||||
|  | ||||
|     The corresponding Emscripten bug is at: | ||||
|     https://github.com/kripken/emscripten/issues/3788 | ||||
|  | ||||
|     Therefore, SSE2 optimization is currently disabled in CMakeLists.txt. | ||||
|  | ||||
| -   If WEBP_ENABLE_SIMD is set to 1 the JavaScript version (webp.js) will be | ||||
|     disabled as wasm2js does not support SIMD. | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
|       noInitialRun : true | ||||
|     }; | ||||
|   </script> | ||||
|   <script src="./webp_wasm.js"></script> | ||||
|   <script type="text/javascript"> | ||||
|  | ||||
| 'use strict'; | ||||
| @@ -16,40 +17,25 @@ | ||||
| // main wrapper for the function decoding a WebP into a canvas object | ||||
| var WebpToCanvas; | ||||
|  | ||||
| function init() { | ||||
|   var xhr = new XMLHttpRequest(); | ||||
|   xhr.open('GET', 'webp_wasm.wasm', true); | ||||
|   xhr.responseType = 'arraybuffer'; | ||||
|   xhr.onload = function() { | ||||
|     Module.wasmBinary = xhr.response; | ||||
|     var script = document.createElement('script'); | ||||
|     script.src = "webp_wasm.js"; | ||||
|     document.body.appendChild(script); | ||||
|   }; | ||||
|   xhr.send(null); | ||||
| } | ||||
| window.onload = init; | ||||
| Module.onRuntimeInitialized = async () => { | ||||
|   // wrapper for the function decoding a WebP into a canvas object | ||||
|   WebpToCanvas = Module.cwrap('WebPToSDL', 'number', ['array', 'number']); | ||||
| }; | ||||
|  | ||||
| function decode(webp_data, canvas_id) { | ||||
|   var result; | ||||
|   if (Module["asm"] != undefined) { | ||||
|     // wrapper for the function decoding a WebP into a canvas object | ||||
|     WebpToCanvas = Module.cwrap('WebPToSDL', 'number', ['array', 'number']); | ||||
|     // get the canvas to decode into | ||||
|     var canvas = document.getElementById(canvas_id); | ||||
|     if (canvas == null) return; | ||||
|     // clear previous picture (if any) | ||||
|     Module.canvas = canvas; | ||||
|     canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); | ||||
|     // decode and measure timing | ||||
|     var start = new Date(); | ||||
|     var ret = WebpToCanvas(webp_data, webp_data.length); | ||||
|     var end = new Date(); | ||||
|     var decode_time = end - start; | ||||
|     result = 'decoding time: ' + decode_time +' ms.'; | ||||
|   } else { | ||||
|     result = "WASM module not finished loading! Please retry"; | ||||
|   } | ||||
|   // get the canvas to decode into | ||||
|   var canvas = document.getElementById(canvas_id); | ||||
|   if (canvas == null) return; | ||||
|   // clear previous picture (if any) | ||||
|   Module.canvas = canvas; | ||||
|   canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); | ||||
|   // decode and measure timing | ||||
|   var start = new Date(); | ||||
|   var ret = WebpToCanvas(webp_data, webp_data.length); | ||||
|   var end = new Date(); | ||||
|   var decodeTime = end - start; | ||||
|   result = 'decoding time: ' + decodeTime +' ms.'; | ||||
|   // display timing result | ||||
|   var speed_result = document.getElementById('timing'); | ||||
|   if (speed_result != null) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user