Skip to content

Commit

Permalink
[WIP] Add port of SDL3
Browse files Browse the repository at this point in the history
So far I haven't got any browser tests working.

Fixes: #23608
  • Loading branch information
sbc100 committed Feb 10, 2025
1 parent 558635e commit 0a999bd
Show file tree
Hide file tree
Showing 8 changed files with 899 additions and 85 deletions.
100 changes: 51 additions & 49 deletions test/browser/test_sdl2_canvas_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,73 +5,75 @@

#include <assert.h>
#include <SDL.h>
#include <emscripten.h>
#include <emscripten/em_asm.h>

static void sdlError(const char *str)
{
fprintf(stderr, "Error at %s: %s\n", str, SDL_GetError());
emscripten_force_exit(1);
static void sdlError(const char* str) {
fprintf(stderr, "Error at %s: %s\n", str, SDL_GetError());
exit(1);
}

void draw(SDL_Window *window, SDL_Surface *surface) {
int x, y;
void draw(SDL_Window* window, SDL_Surface* surface) {
int x, y;

if (SDL_MUSTLOCK(surface)) {
if (SDL_LockSurface(surface) != 0) sdlError("SDL_LockSurface");
}
if (SDL_MUSTLOCK(surface)) {
if (SDL_LockSurface(surface) != 0)
sdlError("SDL_LockSurface");
}

for (y = 0; y < 256; y++) {
Uint32 *p = (Uint32 *)(((Uint8 *)surface->pixels) +
surface->pitch * y);
for (x = 0; x < 256; x++) {
*(p++) = SDL_MapRGB(surface->format, x, x ^ y, y);
}
for (y = 0; y < 256; y++) {
Uint32* p = (Uint32*)(((Uint8*)surface->pixels) + surface->pitch * y);
for (x = 0; x < 256; x++) {
*(p++) = SDL_MapRGB(surface->format, x, x ^ y, y);
}
}

if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
if (SDL_UpdateWindowSurface(window) != 0)
sdlError("SDL_UpdateWindowSurface");
if (SDL_MUSTLOCK(surface))
SDL_UnlockSurface(surface);
if (SDL_UpdateWindowSurface(window) != 0)
sdlError("SDL_UpdateWindowSurface");
}

void verify(void) {
int res = EM_ASM_INT({
var ctx = Module['canvas'].getContext('2d');
var data = ctx.getImageData(0, 0, 256, 256).data;
var idx = 0;
for (var y = 0; y < 256; y++) {
for (var x = 0; x < 256; x++) {
if (data[idx ] !== x ||
data[idx + 1] !== (x ^ y) ||
data[idx + 2] !== y ||
data[idx + 3] !== 255) {
return 1;
}
idx += 4;
int res = EM_ASM_INT({
var ctx = Module['canvas'].getContext('2d');
var data = ctx.getImageData(0, 0, 256, 256).data;
var idx = 0;
for (var y = 0; y < 256; y++) {
for (var x = 0; x < 256; x++) {
if (data[idx ] !== x ||
data[idx + 1] !== (x ^ y) ||
data[idx + 2] !== y ||
data[idx + 3] !== 255) {
return 1;
}
idx += 4;
}
return 0;
});
}
return 0;
});

printf("%s\n", res ? "FAIL" : "PASS");
assert(res == 0);
printf("%s\n", res ? "FAIL" : "PASS");
assert(res == 0);
}

int main(void) {
SDL_Window *window;
SDL_Surface *surface;
SDL_Window* window;
SDL_Surface* surface;

if (SDL_Init(SDL_INIT_VIDEO) != 0) sdlError("SDL_Init");
if (SDL_Init(SDL_INIT_VIDEO) != 0)
sdlError("SDL_Init");

window = SDL_CreateWindow("SDL 2 test",
0, 0,
256, 256,
SDL_WINDOW_SHOWN);
if (window == NULL) sdlError("SDL_CreateWindow");
surface = SDL_GetWindowSurface(window);
if (surface == NULL) sdlError("SDL_GetWindowSurface");
window = SDL_CreateWindow("SDL 2 test", 0, 0, 256, 256, SDL_WINDOW_SHOWN);
if (window == NULL) {
sdlError("SDL_CreateWindow");
}
surface = SDL_GetWindowSurface(window);
if (surface == NULL) {
sdlError("SDL_GetWindowSurface");
}

draw(window, surface);
draw(window, surface);

verify();
return 0;
verify();
return 0;
}
72 changes: 36 additions & 36 deletions test/browser/test_sdl2_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,40 @@

#include <emscripten.h>

int main(int argc, char *argv[])
{
SDL_Window *window;

if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}

window = SDL_CreateWindow(
"sdl2_misc",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
100,
100,
0
);

EM_ASM({
assert(document.title === 'sdl2_misc');
});
const char* intended = "a custom window title";
SDL_SetWindowTitle(window, intended);
const char* seen = SDL_GetWindowTitle(window);
if (strcmp(intended, seen) != 0) {
printf("Got a weird title back: %s\n", seen);
return 1;
}
EM_ASM({
assert(document.title === 'a custom window title');
});

SDL_DestroyWindow(window);
SDL_Quit();

return 0;
int main(int argc, char *argv[]) {
SDL_Window *window;

if (SDL_Init(SDL_INIT_VIDEO) != 0) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}

window = SDL_CreateWindow(
"sdl2_misc",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
100,
100,
0
);

EM_ASM({
assert(document.title === 'sdl2_misc');
});
const char* intended = "a custom window title";
SDL_SetWindowTitle(window, intended);
const char* seen = SDL_GetWindowTitle(window);
if (strcmp(intended, seen) != 0) {
printf("Got a weird title back: %s\n", seen);
return 1;
}

EM_ASM({
assert(document.title === 'a custom window title');
});

SDL_DestroyWindow(window);
SDL_Quit();

return 0;
}
85 changes: 85 additions & 0 deletions test/browser/test_sdl3_canvas_write.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2015 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License. Both these licenses can be
// found in the LICENSE file.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL3/SDL.h>
#include <emscripten/em_asm.h>

static void sdlError(const char* str) {
fprintf(stderr, "Error at %s: %s\n", str, SDL_GetError());
exit(1);
}

void draw(SDL_Window* window, SDL_Surface* surface) {
int x, y;

if (SDL_MUSTLOCK(surface)) {
if (!SDL_LockSurface(surface)) {
sdlError("SDL_LockSurface");
}
}

for (y = 0; y < 256; y++) {
Uint32* p = (Uint32*)(((Uint8*)surface->pixels) + surface->pitch * y);
for (x = 0; x < 256; x++) {
*(p++) = SDL_MapSurfaceRGB(surface, x, x ^ y, y);
}
}

if (SDL_MUSTLOCK(surface)) {
SDL_UnlockSurface(surface);
}
if (!SDL_UpdateWindowSurface(window)) {
sdlError("SDL_UpdateWindowSurface");
}
}

void verify(void) {
int res = EM_ASM_INT({
var ctx = Module['canvas'].getContext('2d');
var data = ctx.getImageData(0, 0, 256, 256).data;
var idx = 0;
for (var y = 0; y < 256; y++) {
for (var x = 0; x < 256; x++) {
if (data[idx ] !== x ||
data[idx + 1] !== (x ^ y) ||
data[idx + 2] !== y ||
data[idx + 3] !== 255) {
return 1;
}
idx += 4;
}
}
return 0;
});

printf("%s\n", res ? "FAIL" : "PASS");
assert(res == 0);
}

int main(void) {
SDL_Window* window;
SDL_Surface* surface;

if (!SDL_Init(SDL_INIT_VIDEO)) {
sdlError("SDL_Init");
}

window = SDL_CreateWindow("SDL 2 test", 256, 256, 0);
if (window == NULL) {
sdlError("SDL_CreateWindow");
}
surface = SDL_GetWindowSurface(window);
if (surface == NULL) {
sdlError("SDL_GetWindowSurface");
}

draw(window, surface);

verify();
return 0;
}
45 changes: 45 additions & 0 deletions test/browser/test_sdl3_misc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2025 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/

#include "SDL3/SDL.h"

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include <emscripten.h>

int main(int argc, char* argv[]) {
SDL_Window* window;

if (!SDL_Init(SDL_INIT_VIDEO)) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
assert(false);
}

window = SDL_CreateWindow("sdl3_misc", 100, 100, 0);

EM_ASM({
assert(document.title == 'sdl3_misc');
});
const char* intended = "a custom window title";
SDL_SetWindowTitle(window, intended);
const char* seen = SDL_GetWindowTitle(window);
if (strcmp(intended, seen) != 0) {
printf("Got a weird title back: %s\n", seen);
assert(false);
}
EM_ASM({
assert(document.title == 'a custom window title');
});

SDL_DestroyWindow(window);
SDL_Quit();

return 0;
}
7 changes: 7 additions & 0 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3245,6 +3245,13 @@ def test_sdl2_mixer_music(self, formats, flags, music_name):
args += ['-lc++', '-lc++abi']
self.btest_exit('test_sdl2_mixer_music.c', args=args)

def test_sdl3_misc(self):
self.emcc_args.append('-Wno-experimental')
self.btest_exit('test_sdl3_misc.c', args=['-sUSE_SDL=3'])

def test_sdl3_canvas_write(self):
self.btest_exit('test_sdl3_canvas_write.c', args=['-sUSE_SDL=3'])

@requires_graphics_hardware
@no_wasm64('cocos2d ports does not compile with wasm64')
def test_cocos2d_hello(self):
Expand Down
7 changes: 7 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -2476,6 +2476,13 @@ def test_sdl2_linkable(self):
self.emcc(test_file('browser/test_sdl2_misc.c'), ['-sLINKABLE', '-sUSE_SDL=2'], output_filename='a.out.js')
self.emcc(test_file('browser/test_sdl2_misc.c'), ['-sLINKABLE', '--use-port=sdl2'], output_filename='a.out.js')

def test_sdl3_linkable(self):
# Ensure that SDL2 can be built with LINKABLE. This implies there are no undefined
# symbols in the library (because LINKABLE includes the entire library).
self.emcc_args.append('-Wno-experimental')
self.emcc(test_file('browser/test_sdl3_misc.c'), ['-sLINKABLE', '-sUSE_SDL=3'], output_filename='a.out.js')
self.emcc(test_file('browser/test_sdl3_misc.c'), ['-sLINKABLE', '--use-port=sdl3'], output_filename='a.out.js')

@requires_network
def test_sdl2_gfx_linkable(self):
# Same as above but for sdl2_gfx library
Expand Down
Loading

0 comments on commit 0a999bd

Please sign in to comment.