mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-19 20:08:28 +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:
parent
a429c0de64
commit
24d7f9cb6e
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user