Skip to content

Conversation

@junov
Copy link
Member

@junov junov commented Oct 7, 2016

This change defines the OffscreenCanvas and
OffscreenCanvasRenderingContext2d interfaces, based on the feature
proposal found here: https://wiki.whatwg.org/wiki/OffscreenCanvas

@junov
Copy link
Member Author

junov commented Oct 7, 2016

Please take a look @mephisto41, @kenrussell, @grorg

Copy link
Member

@kenrussell kenrussell left a comment

Choose a reason for hiding this comment

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

Very nice. Looks excellent to me overall. Two very minor points.

source Outdated

<p>Returns null if the given context ID is not supported, if the canvas has already been
initialized with the other context type (e.g. trying to get a "<code
initialized with an other context type (e.g. trying to get a "<code
Copy link
Member

Choose a reason for hiding this comment

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

an other -> another?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

source Outdated
context that is created from a <code>canvas</code> element. There is also a specification that defines a "<code data-x="canvas-context-webgl">webgl</code>" context. <ref spec=WEBGL></p>

<p>Returns null if the given context ID is not supported, if the canvas has already been
initialized with the other context type (e.g. trying to get a "<code
Copy link
Member

Choose a reason for hiding this comment

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

the other -> another

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

@domenic domenic added the addition/proposal New features or enhancements label Oct 10, 2016
source Outdated
unrestricted double quality = 1.0;
};

[Constructor(unsigned long width, unsigned long height), Exposed=(Window,Worker)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have [EnforceRange] for both width and height. I was really hoping to minimize ambiguity in the future.

Copy link
Member Author

Choose a reason for hiding this comment

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

That sounds reasonable to me. The modulo conversions dictated by WebIDL will not give anything useful here, so it might as well throw.

source Outdated
<p>Returns an object that exposes an API for drawing on the offscreen canvas. The first
argument specifies the desired API, either "<code
data-x="offscreencanvas-context-2d">2d</code>", or "<code
data-x="canvas-context-webgl">webgl</code>". Subsequent arguments are handled by that
Copy link
Contributor

Choose a reason for hiding this comment

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

Could it be webgl2?

Copy link
Contributor

Choose a reason for hiding this comment

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

Now that I read more, I realized that we just use webgl to refer to both. So please ignore my previous comment in here.

Copy link
Member Author

Choose a reason for hiding this comment

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

webgl2 is still a valid context type that should have its own line in the getContext table. My thinking was that we could add it in a separate change, at the same time as we add it to HTMLCanvasElement's version of getContext.

Copy link
Member

@annevk annevk left a comment

Choose a reason for hiding this comment

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

A whole lot of style nits basically. I don't think I know enough to critique the algorithms. As for the style nits, please go through the entire diff for each of them, I didn't point them all out individually. As a heads up, probably requires another style review after these are addressed. Hope that's okay.

(Also, very exciting to see workers finally getting some graphics.)

source Outdated

<p>When its <span data-x="concept-canvas-context-mode">canvas context mode</span> is <span
data-x="concept-canvas-placeholder">placeholder</span>, a <code>canvas</code> element has no
rendering context. It serves as a placeholder for an OffscreenCanvas object, and the content of
Copy link
Member

@annevk annevk Oct 10, 2016

Choose a reason for hiding this comment

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

Here it needs <code>.

source Outdated

USVString <span data-x="dom-canvas-toDataURL">toDataURL</span>(optional DOMString type, optional any quality);
void <span data-x="dom-canvas-toBlob">toBlob</span>(<span>BlobCallback</span> _callback, optional DOMString type, optional any quality);
OffscreenCanvas <span data-x="dom-canvas-transferControlToOffscreen">transferControlToOffscreen</span>();
Copy link
Member

Choose a reason for hiding this comment

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

Here OffScreenCanvas needs to be wrapped in <span>.

source Outdated

<dd>

<p>Returns a newly created OffscreenCanvas object that uses this canvas element as a
Copy link
Member

@annevk annevk Oct 12, 2016

Choose a reason for hiding this comment

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

<code> for OffscreenCanvas and canvas.

Copy link
Member

Choose a reason for hiding this comment

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

You should basically go through the entire diff, since it seems to have happened quite often.

source Outdated
<li><p>Create a new OffscreenCanvas object with its width and height equal to the
values of the <code data-x="attr-canvas-width">width</code> and <code
data-x="attr-canvas-height">height</code> content attributes of this <code>canvas</code>
element.</p></li>
Copy link
Member

Choose a reason for hiding this comment

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

I would prefer it if you assign the create result to a variable and use that in the remainder of these steps.

source Outdated
attribute unsigned long width;
attribute unsigned long height;

OffscreenRenderingContext? <code data-x="offscreencanvas-getContext">getContext</code>(DOMString contextId, any... arguments);
Copy link
Member

Choose a reason for hiding this comment

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

Needs <span>. Can we improve upon getContext() here by making it take an enum and a more restricted set of arguments or is that a lost cause?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can we improve upon getContext() here by making it take an enum and a more restricted set of arguments or is that a lost cause?

We could make contextId it an enum. This means that passing an unrecognized context Id will result in an exception being thrown instead of the function returning null, as is currently the case with . I am not sure how to weigh cleanliness of an enum vs. breaking the mold of HTMLCanvasElement.getContext.

For the "arguments" argument we are using dictionaries for all context types, but each context type has its own dictionary definition. For example the WebGL spec defines creation options that have no meaning for 2D contexts. I would like to use a dictionary for the IDL here but I am not sure what would be the right pattern for spec'ing this correctly. Perhaps we could have a union typedef? That's a bit weird though because the bindings cannot determine which dictionary type an associative array should be mapped to (it depends on contextId). Another option would be to have a shared dictionary type that contains all creation options used by all context types. But that would force different context types that have options with the same name to use the same types for those options. The shared dictionary approach is actually what we did for Blink's internal IDL. But how would that work in the spec? We could define a shared dictionary in this spec and put a partial dictionary definition in the WebGL spec in order to add WebGL-specific members to the shared dictionary. Does that sound reasonable?

Copy link
Member

Choose a reason for hiding this comment

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

That sounds fine. It's an implicit requirement that all context types have to have the same default set of values for the common entries in this dictionary. For example, the "alpha" dictionary entry used by the 2D and WebGL contexts here:

https://html.spec.whatwg.org/multipage/scripting.html#2dcontext:dom-canvas-getcontext
https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.2

has to be a boolean in both, and default to true. This is needed in order to avoid custom binding code for HTMLCanvasElement's getContext method. Web IDL doesn't allow specializing the behavior of the "arguments" dictionary based on which contextId was passed. (All of the custom binding code for this method was removed in Blink some time ago.)

Copy link
Member

Choose a reason for hiding this comment

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

Changing to a shared dictionary was previously discussed in #595 (comment) - maybe continue discussion there? @smaug---- did not seem to like the merged dictionary idea there.

source Outdated
data-x="offscreencanvas-context-mode">context mode</span> is not equal to <span
data-x="offscreencanvas-context-none">none</span>, throw an
<span>"<code>InvalidStateError</code>"</span> <code>DOMException</code>, and abort these
steps.</p></li>
Copy link
Member

Choose a reason for hiding this comment

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

No need for abort these steps. Throwing does that.

source Outdated

<p class="tablenote"><small>* Vendors may define experimental contexts using the syntax <code
data-x=""><var>vendorname</var>-<var>context</var></code>, for example, <code
data-x="">moz-3d</code>.</small></p>
Copy link
Member

Choose a reason for hiding this comment

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

If we still have this text we should probably remove it. I think the whole industry has accepted that prefixes are bad now.

source Outdated
data-x="offscreencanvas-transferToImageBitmap">transferToImageBitmap</code>()</dt>

<dd>
<p>Returns a newly created ImageBitmap object with the image in the OffscreenCanvas.
Copy link
Member

@annevk annevk Oct 12, 2016

Choose a reason for hiding this comment

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

Lacks <code> for two objects (though again, I don't think I have noted them all). OffscreenCanvas should also be followed by " object" consistently.

<p>The <dfn><code
data-x="offscreencanvas-convertToBlob">convertToBlob(<var>options</var>)</code></dfn> method,
when invoked, must run the following steps:</p>
<ol>
Copy link
Member

Choose a reason for hiding this comment

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

Newline before <ol>.

source Outdated

<pre class="idl">interface <dfn>OffscreenCanvasRenderingContext2D</dfn> {
void commit();
readonly attribute OffscreenCanvas <dfn data-x="offscreencontext2d-canvas">canvas</dfn>;
Copy link
Member

Choose a reason for hiding this comment

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

<span>

Copy link
Member

Choose a reason for hiding this comment

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

Also the IDL below needs lots of <span> love.

annevk added a commit that referenced this pull request Oct 12, 2016
Including the oddly specific language for <canvas>’s getContext()
feature that was added for Opera’s extensions back in the day if I
remember correctly.

Noticed we still had this while reviewing #1876.
@junov junov added the do not merge yet Pull request must not be merged per rationale in comment label Oct 12, 2016
@junov
Copy link
Member Author

junov commented Oct 12, 2016

Since mozilla's implementation is nearly complete, adding "do not merge yet" label until this PR is checked against that implementation and that any compatibility issues are either challenged and corrected this PR review, or resolved in the implementation.

@junov
Copy link
Member Author

junov commented Oct 12, 2016

Just realized that OffscreenCanvas needs to be an EventTarget so that WebGL contexts can dispatch context lost/restored events. Any objections to that?

@junov
Copy link
Member Author

junov commented Oct 14, 2016

I have received feedback from Brandon Jones (co-editor of the WebVR spec) and from the Google maps team regarding the lack of ability to resize canvases. Though this may not be a deal breaker for 2D canvases (you can just create a new canvas with the new size and discard the old one), for WebGL it is another story. Recreating canvases for the purpose of a resize is prohibitively expensive for WebGL applications because it means that all the resources (e.g. textures, shaders, etc.) would need to be recreated in a new context, which is not acceptable for many use cases. I intend to make that change in this PR.

@annevk
Copy link
Member

annevk commented Oct 14, 2016

@junov can we do resizing separately or is that specifically about OffscreenCanvas? This is already a pretty big PR, if we can divide things up that'd be nice.

@junov
Copy link
Member Author

junov commented Oct 14, 2016

That is a good idea, there might be quite a bit of complexity in spec'ing the resizing behavior.
The current PR has text that specifically states that resizing is not allowed. I will at least remove that from this PR.

@junov junov removed the do not merge yet Pull request must not be merged per rationale in comment label Nov 11, 2016
@junov
Copy link
Member Author

junov commented Nov 11, 2016

Applied all the fixes requested above except for:

  • resizing: will do it in a follow-up PR
  • refactoring the getContext dictionary argument. As pointed-out by @zcorpan there are objections to this in another thread. Keeping this for future consideration.

Noteworthy: I did make getContext use an enum instead of a string for the context type.

@domenic
Copy link
Member

domenic commented Nov 11, 2016

Noteworthy: I did make getContext use an enum instead of a string for the context type.

That's a normative change that makes it start throwing when "asdf" is passed in.

@junov
Copy link
Member Author

junov commented Nov 11, 2016

That's a normative change that makes it start throwing when "asdf" is passed in.

Correct. I did not touch the existing HTMLCanvasElement.getContext to avoid any compat issues.
I only did the enum thing for the new OffscreenCanvas.getContext.

Copy link
Member

@domenic domenic left a comment

Choose a reason for hiding this comment

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

Lots of nits, but I'm very excited for this!

source Outdated
must run the steps in the cell of the following table whose column header describes the
<code>canvas</code> element's <span data-x="concept-canvas-context-mode">canvas context
mode</span> and whose row header describes the method's first argument.</p>
mode</span> and whose row header describes the method's first argument. Except when the <span
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather just update the table to have a new column? It seems like a nice property that all the different modes are represented by columns in the table.

source Outdated
data-x="dom-canvas-transferControlToOffscreen">transferControlToOffscreen</code>()</dt>

<dd>
<p>Returns a newly created <code>OffscreenCanvas</code> object that uses <b>this</b>
Copy link
Member

Choose a reason for hiding this comment

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

"the canvas, not "this canvas", in this context

source Outdated
<p>Returns a newly created <code>OffscreenCanvas</code> object that uses <b>this</b>
<code>canvas</code> element as a placeholder. Once a canvas element has become a placeholder
for an <code>OffscreenCanvas</code> object, its intrinsic size can no longer be changed, and it
can not have a rendering context. The content of the placeholder canvas is updated by calling
Copy link
Member

Choose a reason for hiding this comment

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

s/can not/cannot/

source Outdated

<dd>
<p>Returns a newly created <code>OffscreenCanvas</code> object that uses <b>this</b>
<code>canvas</code> element as a placeholder. Once a canvas element has become a placeholder
Copy link
Member

Choose a reason for hiding this comment

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

s/a canvas element/the canvas/

source Outdated
<code>canvas</code> element as a placeholder. Once a canvas element has become a placeholder
for an <code>OffscreenCanvas</code> object, its intrinsic size can no longer be changed, and it
can not have a rendering context. The content of the placeholder canvas is updated by calling
the <code data-x="offscreencontext-commit">commit</code> method of the
Copy link
Member

Choose a reason for hiding this comment

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

commit() as the link text

source Outdated

</ol>

<p>The <dfn><code data-x="offscreencontext2d-commit">commit</code></dfn> method, when invoked, must
Copy link
Member

Choose a reason for hiding this comment

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

commit()

source Outdated

<pre class="idl">interface <dfn>OffscreenCanvasRenderingContext2D</dfn> {
void commit();
readonly attribute <span>OffscreenCanvas</span> <dfn data-x="offscreencontext2d-canvas">canvas</dfn>;
Copy link
Member

Choose a reason for hiding this comment

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

This should be a <span> not a <dfn>; see below for how to define it.

source Outdated

<li><p>Create a new <code>OffscreenCanvasRenderingContext2D</code> object.</p></li>

<li><p>Initialize its <code data-x="offscreencontext2d-canvas">canvas</code> attribute to point to
Copy link
Member

Choose a reason for hiding this comment

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

It would be better to make "associated OffscreenCanvas" something that each OCRC2D has, like it has a bitmap and alpha flag. Then you define the canvas attribute, on getting, to return this OCRC2D's associated OffscreenCanvas, and in this algorithm, you set the associated OffscreenCanvas. This also makes it so that commit()'s algorithm can simply say "this OCRC2D's associated OffscreenCanvas" instead of "the OffscreenCanvas from which this context was created"

source Outdated
where the <code data-x="offscreencontext2d-commit">commit</code> method is invioked from a Worker
and the <span>event loop</span> of the <span
data-x="offscreencanvas-placeholder">placeholder</span> <code>canvas</code> element's
<span>browsing context</span> is busy. However, such shortcuts must not have any\
Copy link
Member

Choose a reason for hiding this comment

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

Remove stray \

source Outdated
<span>browsing context</span> is busy. However, such shortcuts must not have any\
script-observable side-effects. This means that the committed bitmap still needs to be sent to
the <span data-x="offscreencanvas-placeholder">placeholder</span> <code>canvas</code> element, in
case the element is used as a <code>CanvasImageSource</code>, or in case toDataURL or toBlob are
Copy link
Member

Choose a reason for hiding this comment

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

Link toDataURL() and toBlob(), and add parens

@junov
Copy link
Member Author

junov commented Nov 15, 2016

Changes requested by @domenic: done.

@domenic
Copy link
Member

domenic commented Nov 15, 2016

Pushed some more review tweaks. The only remaining thing I noticed is, what if converting to a blob fails? That possibility doesn't seem to be accounted for. I was thinking of adding a sentence like "If the serialization process fails for any reason, reject result with ..." to the end of step 6. But I wasn't sure what a good DOMException would be. Maybe "EncodingError"? Or maybe it just never fails?

@domenic
Copy link
Member

domenic commented Nov 15, 2016

Oh. Are OffscreenCanvas's width and height supposed to be mutable? If so we need to define algorithms for their setters. Maybe that is the resizing thing mentioned above? Or maybe they should just be made readonly.

@junov
Copy link
Member Author

junov commented Nov 15, 2016

For blob failures: should we reject with what ever exception was thrown during serialization?

Regarding the setters for width and height. That was brought up earlier in this thread. @annevk suggested we take care of defining the resizing behavior in a follow-up PR to avoid adding more weight to this one, which is already quite big.

@domenic
Copy link
Member

domenic commented Nov 15, 2016

For blob failures: should we reject with what ever exception was thrown during serialization?

Sure, but what exception would that be? I mean, the C++ code will throw an exception, but what JS-facing exception would result?

Regarding the setters for width and height. That was brought up earlier in this thread. @annevk suggested we take care of defining the resizing behavior in a follow-up PR to avoid adding more weight to this one, which is already quite big.

That seems reasonable. Can we mark them readonly for now then?

@junov
Copy link
Member Author

junov commented Nov 15, 2016

tweaks lgtm

@junov
Copy link
Member Author

junov commented Nov 15, 2016

Can we mark them readonly for now then?

sure.

Sure, but what exception would that be?

After taking a closer look, I don't think the encode can fail other than an out-of-memory error, which typically crashes the browser. For ArrayBuffers, we throw a RangeError exception when allocation fails do we want to offer that here?

@domenic
Copy link
Member

domenic commented Nov 15, 2016

If there's no reason it can fail besides OOM, I'm OK leaving that for a separate discussion/PR. We'd probably want to change toBlob() as well in some way (although it doesn't have an error channel so I'm not sure what we'd do there).

@junov
Copy link
Member Author

junov commented Nov 15, 2016

Summoning @mephisto41

@mephisto41
Copy link

Sorry for late reply. I think this is very good. I'm very excited to see this becomes spec. Thanks for it.

data-x="concept-canvas-placeholder">placeholder</span>, a <code>canvas</code> element has no
rendering context. It serves as a placeholder for an <code>OffscreenCanvas</code> object, and
the content of the <code>canvas</code> element is updated by calling the <code
data-x="offscreencontext-commit">commit()</code> method of the <code>OffscreenCanvas</code>
Copy link
Member

Choose a reason for hiding this comment

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

This should be data-x="dom-OffscreenContext-commit" (and below).

source Outdated

[<span data-x="dom-OffscreenCanvas">Constructor</span>([EnforceRange] unsigned long long width, [EnforceRange] unsigned long long height), Exposed=(Window,Worker)]
interface <dfn>OffscreenCanvas</dfn> : <span>EventTarget</span> {
readonly attribute unsigned long long <span data-x="offscreencanvas-width">width</span>;
Copy link
Member

Choose a reason for hiding this comment

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

dom-OffscreenCanvas-width etc.

@junov
Copy link
Member Author

junov commented Nov 16, 2016

@annevk out of curiosity, what exactly does the "dom-" prefix mean? I assumed we used it for interfaces related to the dom, but that is clearly not the case.

@junov
Copy link
Member Author

junov commented Nov 16, 2016

Done. I put the "dom-OffscreenCanvas" prefix for the x-ref labels of things that are symbols in the OffscreenCanvas interface.

@annevk
Copy link
Member

annevk commented Nov 16, 2016

@junov it's a bit of a historical convention at this point, but since it also dictates the IDs these definitions end up having it's nice to be consistent so that if you know the interface and its members you can URL hack your way to the definitions quite easily.

@domenic domenic merged commit aedc72d into whatwg:master Nov 16, 2016
@junov
Copy link
Member Author

junov commented Nov 16, 2016

\o/

@xidachen
Copy link
Contributor

Yay!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

addition/proposal New features or enhancements topic: canvas

Development

Successfully merging this pull request may close these issues.

7 participants