Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Workers to do tile decompression and unpremultiply #9208

Closed
wants to merge 1 commit into from

Conversation

Cwiiis
Copy link
Contributor

@Cwiiis Cwiiis commented Jun 3, 2024

  • Resolves: #
  • Target version: master

Summary

Two patches; the first fixes a bug where if we receive new keyframe tiledata and need to ensure the canvas, we end up decompressing/unpremultiplying/putting the old data unnecessarily (I think). The second uses a worker to offload the majority of tile image data decompression and unpremultiplying from the main thread and improves response during large update operations (such as scrolling through a document).

The code is not properly formatted yet, I'm opening this PR now and will update it with fixes once I figure out what those fixes are...

Checklist

  • Code is properly formatted
  • All commits have Change-Id
  • I have run tests with make check
  • I have issued make run and manually verified that everything looks okay
  • Documentation (manuals or wiki) has been updated or is not required

Copy link

welcome bot commented Jun 3, 2024

Thanks for opening this pull request!

Things that will help get your PR across the finish line:

@Cwiiis Cwiiis force-pushed the messing-with-workers branch 3 times, most recently from 3430ea8 to f6b9b8e Compare June 5, 2024 15:09
browser/src/core/MessagePreProcessor.js Fixed Show fixed Hide fixed
break;

default:
console.error('Unrecognised preprocessor message', e);

Check warning

Code scanning / CodeQL

Log injection Medium

Log entry depends on a
user-provided value
.

console.log('MessagePreProcessor initialised', self.fzstd);

function onMessage(e) {

Check warning

Code scanning / CodeQL

Missing origin verification in `postMessage` handler Medium

Postmessage handler has no origin check.
@Cwiiis Cwiiis force-pushed the messing-with-workers branch 4 times, most recently from 672568b to 823be3a Compare June 7, 2024 12:05
lastMask = data[rleMaskOffset++];
}
if (!(lastMask & bitToCheck)) {
this.lastPixel.set(data.subarray(pixSrc, pixSrc+4))

Check notice

Code scanning / CodeQL

Semicolon insertion Note

Avoid automated semicolon insertion (95% of all statements in
the enclosing function
have an explicit semicolon).
break;

default:
console.error('Unrecognised preprocessor message', e);

Check warning

Code scanning / CodeQL

Log injection Medium

Log entry depends on a
user-provided value
.
var keyframeBufferSize = 0;
var keyframeBuffer;

function onMessage(e) {

Check warning

Code scanning / CodeQL

Missing origin verification in `postMessage` handler Medium

Postmessage handler has no origin check.
Pre-allocate decompression buffers and use a Worker to decompress and
unpremultiply tile data asynchronously while avoiding memory allocation/
deallocation thrashing.

Signed-off-by: Chris Lord <[email protected]>
Change-Id: I2282e3df8bf40bdc3a2381880d46df33f2451758
Copy link
Contributor

@mmeeks mmeeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok - this needs more work; I don't think we can merge it as-is I'm afraid.


if ('undefined' === typeof window) {
importScripts('../../node_modules/fzstd/umd/index.js');
importScripts('../layer/tile/CanvasTileUtils.js');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that this has not been tested with a bundlified product build (?) or do we distribute CanvasTileUtils.js on its own ?

if (alpha === 0) {
data.fill(0, i, i + 3);
} else if (alpha !== 255) {
data[i] = Math.ceil((data[i] * 255) / alpha);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use a 64k byte lookup table here as some of the core LibreOffice code does =)

lastMask = data[rleMaskOffset++];
}
if (!(lastMask & bitToCheck)) {
this.lastPixel.set(data.subarray(pixSrc, pixSrc + 4));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we decided that subarray was unfeasibly slow on firefox, and we didn't want to over-use it ?

@@ -459,7 +484,14 @@ app.definitions.Socket = L.Class.extend({
// process so - slurp and then emit at idle - its faster to delay!
_slurpMessage: function(e) {
this._extractTextImg(e);
if (e.image && e.image.rawData && this._worker) {
this._queueWorkerTileProcessing(e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I reading this right that we take 'tile:' messages only - and we potentially then emit them out of order with subsequent 'delta:' and 'update:' messages which could arrive before the tiles are de-compressed by the thread - that is likely to lead to corrupted pixels.
Hmm.

@Cwiiis
Copy link
Contributor Author

Cwiiis commented Oct 4, 2024

I'm going to close this as I have a newer, better version of the patch in a different branch. I'll likely need advice resolving some of these comments - I'll try to flag these issues explicitly.

@Cwiiis Cwiiis closed this Oct 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants