summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webcodecs/videoFrame-texImage.any.js
blob: 2eab6c8cde30c6eb3cb728d3d326e3ac321840cc (plain)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// META: global=window,dedicatedworker
// META: script=/webcodecs/utils.js
// META: script=/webcodecs/webgl-test-utils.js

function testGLCanvas(gl, width, height, expectedPixel, assertCompares) {
  var colorData =
      new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
  gl.readPixels(
      0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA,
      gl.UNSIGNED_BYTE, colorData);
  assertCompares(gl.getError(), gl.NO_ERROR);

  const kMaxPixelToCheck = 128 * 96;
  let step = width * height / kMaxPixelToCheck;
  step = Math.round(step);
  step = (step < 1) ? 1 : step;
  for (let i = 0; i < 4 * width * height; i += (4 * step)) {
    assertCompares(colorData[i], expectedPixel[0]);
    assertCompares(colorData[i + 1], expectedPixel[1]);
    assertCompares(colorData[i + 2], expectedPixel[2]);
    assertCompares(colorData[i + 3], expectedPixel[3]);
  }
}

function testTexImage2DFromVideoFrame(
    width, height, useTexSubImage2D, expectedPixel) {
  let vfInit =
      {format: 'RGBA', timestamp: 0, codedWidth: width, codedHeight: height};
  let argbData = new Uint32Array(vfInit.codedWidth * vfInit.codedHeight);
  argbData.fill(0xFF966432);  // 'rgb(50, 100, 150)';
  let frame = new VideoFrame(argbData, vfInit);

  let canvas;
  if (self.HTMLCanvasElement) {
    canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
  } else
    canvas = new OffscreenCanvas(width, height);
  let gl = canvas.getContext('webgl');

  let program = WebGLTestUtils.setupTexturedQuad(gl);
  gl.clearColor(0, 0, 0, 1);
  gl.clearDepth(1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.colorMask(1, 1, 1, 0);  // Disable any writes to the alpha channel.
  let textureLoc = gl.getUniformLocation(program, 'tex');

  let texture = gl.createTexture();

  // Bind the texture to texture unit 0.
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // Set up texture parameters.
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

  // Set up pixel store parameters.
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);

  // Upload the videoElement into the texture
  if (useTexSubImage2D) {
    // Initialize the texture to black first
    gl.texImage2D(
        gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
        null);
    gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, frame);
  } else {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame);
  }

  frame.close();

  assert_equals(gl.getError(), gl.NO_ERROR);

  // Point the uniform sampler to texture unit 0
  gl.uniform1i(textureLoc, 0);

  // Draw the triangles
  WebGLTestUtils.drawQuad(gl, [0, 0, 0, 255]);

  // Wait for drawing to complete.
  gl.finish();

  testGLCanvas(gl, width, height, expectedPixel, assert_equals);
}

function testTexImageWithClosedVideoFrame(useTexSubImage2D) {
  let width = 128;
  let height = 128;
  let vfInit =
      {format: 'RGBA', timestamp: 0, codedWidth: width, codedHeight: height};
  let argbData = new Uint32Array(vfInit.codedWidth * vfInit.codedHeight);
  argbData.fill(0xFF966432);  // 'rgb(50, 100, 150)';
  let frame = new VideoFrame(argbData, vfInit);

  let canvas;
  if (self.HTMLCanvasElement) {
    canvas = document.createElement("canvas");
    canvas.width = width;
    canvas.height = height;
  } else
    canvas = new OffscreenCanvas(width, height);
  let gl = canvas.getContext('webgl');

  frame.close();
  if (useTexSubImage2D) {
    gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, frame);
  } else {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame);
  }

  assert_equals(gl.getError(), gl.INVALID_OPERATION);
}

test(_ => {
  testTexImage2DFromVideoFrame(48, 36, false, kSRGBPixel);
}, 'texImage2D with 48x36 srgb VideoFrame.');

test(_ => {
  testTexImage2DFromVideoFrame(48, 36, true, kSRGBPixel);
}, 'texSubImage2D with 48x36 srgb VideoFrame.');

test(_ => {
  testTexImage2DFromVideoFrame(480, 360, false, kSRGBPixel);
}, 'texImage2D with 480x360 srgb VideoFrame.');

test(_ => {
  testTexImage2DFromVideoFrame(480, 360, true, kSRGBPixel);
}, 'texSubImage2D with 480x360 srgb VideoFrame.');

test(_ => {
  testTexImageWithClosedVideoFrame(false);
}, 'texImage2D with a closed VideoFrame.');

test(_ => {
  testTexImageWithClosedVideoFrame(true);
}, 'texSubImage2D with a closed VideoFrame.');