File: resize_offscreencanvas_from_main_thread.cpp

package info (click to toggle)
emscripten 3.1.6~dfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 114,112 kB
  • sloc: ansic: 583,052; cpp: 391,943; javascript: 79,361; python: 54,180; sh: 49,997; pascal: 4,658; makefile: 3,426; asm: 2,191; lisp: 1,869; ruby: 488; cs: 142
file content (105 lines) | stat: -rw-r--r-- 3,456 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <pthread.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/threading.h>
#include <unistd.h>

// Tests that the size of an OffscreenCanvas can be queried and set from the main thread.
// Supporting this is needed since it is very common to resize Canvas size on main thread while relayouting DOM in JavaScript code.

// Define the following to test the scenario where the pthread that owns the OffscreenCanvas is running its own synchronously blocking loop (never yields to event loop).
// If not defined, the pthread that owns the OffscreenCanvas is using emscripten_set_main_loop() so periodically yields back to the event loop.
// #define TEST_SYNC_BLOCKING_LOOP

void thread_local_main_loop()
{
  int w = 0, h = 0;
  emscripten_get_canvas_element_size("#canvas", &w, &h);
  if (w == 699 && h == 299) {
    printf("Observed OffscreenCanvas resize to 699x299 from main thread! Test passed!\n");

#ifndef TEST_SYNC_BLOCKING_LOOP
    emscripten_cancel_main_loop();
#endif

    emscripten_force_exit(0);
  }
  printf("%dx%d\n", w, h);
}

void *thread_main(void *arg)
{
  EmscriptenWebGLContextAttributes attr;
  emscripten_webgl_init_context_attributes(&attr);
  attr.explicitSwapControl = EM_TRUE;
  EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context("#canvas", &attr);
  assert(ctx);

  // To start off, change the size of the OffscreenCanvas, main thread will test that it sees this change.
  printf("pthread resizing OffscreenCanvas to size 355x233.\n");
  emscripten_set_canvas_element_size("#canvas", 355, 233);

  // In pthread, keep polling the canvas size until we see it being changed from the main thread.
#ifdef TEST_SYNC_BLOCKING_LOOP
  for(;;)
  {
    thread_local_main_loop();
    emscripten_current_thread_process_queued_calls();
    usleep(16*1000);
  }
#else
  emscripten_set_main_loop(thread_local_main_loop, 1, 0);
#endif

  return 0;
}

void resize_canvas(void *)
{
  // Test that on the main thread, we can observe size changes to the canvas size.
  int w, h;
  emscripten_get_canvas_element_size("#canvas", &w, &h);
  assert(w == 355 && "We did not observe the effect of pthread having resized OffscreenCanvas");
  assert(h == 233);
  printf("Main thread saw canvas to get resized to %dx%d.\n", w, h);

  // Test that on the main thread, we can also change the size. (pthread listens to see this)
  printf("Main thread resizing OffscreenCanvas to size 699x299.\n");
  emscripten_set_canvas_element_size("#canvas", 699, 299);
}

//should be able to do this regardless of offscreen canvas support
void get_canvas_size()
{
  int w, h;
  emscripten_get_canvas_element_size("#canvas", &w, &h);
  assert(h == 150);
  assert(w == 300);
}

int main()
{
  get_canvas_size();
  if (!emscripten_supports_offscreencanvas()) {
    printf("Current browser does not support OffscreenCanvas. Skipping the rest of the tests.\n");
    return 0;
  }

  pthread_attr_t attr;
  pthread_attr_init(&attr);
  emscripten_pthread_attr_settransferredcanvases(&attr, "#canvas");

  pthread_t thread;
  printf("Creating thread.\n");
  pthread_create(&thread, &attr, thread_main, NULL);
  pthread_detach(thread);

  // Wait for a while, then change the canvas size on the main thread.
  printf("Waiting for 2 seconds for good measure.\n");
  emscripten_async_call(resize_canvas, 0, 2000);
  emscripten_exit_with_live_runtime();
  __builtin_trap();
}