Re: exposing CANVAS or something like it to Web Workers

2012-05-16 Thread
So how to take this forward?

My #1 priority is to get WebGL in workers. Lots of developers have
expressed a need for this from decoding compressed textures in a worker to
offloading thousands of draw calls per frame to a worker. WebGL already
defines sharing mechanisms so at least for the WebGL case I don't need to
solve how to display anything back in the main worker. The worker can draw
to a texture. The main page can use that texture. WebGL/OpenGL already
define that relationship.

But, to get WebGL in a worker I need a way to get a WebGLRenderingContext
into a worker.

Some Ideas

**) Create context in main page, pass to worker*

Pros:

. No new APIs or objects.

Cons:

. Transfer is messy.

What happens to all the entry points and properties to the context object
left in the main page?
What happens to the cavnas parameter on the transferred context?
How do you synchronize the main page setting canvas.width or canvas.height
with the worker trying to render to it?


**) Create a context directly in a Worker (or anywhere for that matter)*

As in var gl = new WebGLRenderingContext

Pros:

. ???

Cons:

. requires defining how the backbuffer size is set.
   Maybe there is no backbuffer for a directly created
WebGLRenderingContext?
. if there is no backbuffer then using one of these contexts to draw into a
texture
  or 2d context is problematic


**) Create an offscreen canvas like object minus HTMLElement parts*
*
*
Pros:

. same or nearly the API as already exists for canvas
. flexible. getContext can return different kinds of context. Maybe only
webgl for now?

Cons:

. ???


Re: exposing CANVAS or something like it to Web Workers

2012-05-16 Thread
On Wed, May 16, 2012 at 12:42 PM, Kenneth Russell k...@google.com wrote:

 On Wed, May 16, 2012 at 12:30 PM, Gregg Tavares (勤) g...@google.com
 wrote:
  So how to take this forward?
 
  My #1 priority is to get WebGL in workers. Lots of developers have
 expressed
  a need for this from decoding compressed textures in a worker to
 offloading
  thousands of draw calls per frame to a worker. WebGL already defines
 sharing
  mechanisms so at least for the WebGL case I don't need to solve how to
  display anything back in the main worker. The worker can draw to a
 texture.
  The main page can use that texture. WebGL/OpenGL already define that
  relationship.
 
  But, to get WebGL in a worker I need a way to get a WebGLRenderingContext
  into a worker.
 
  Some Ideas
 
  *) Create context in main page, pass to worker
 
  Pros:
 
  . No new APIs or objects.
 
  Cons:
 
  . Transfer is messy.
 
  What happens to all the entry points and properties to the context object
  left in the main page?
  What happens to the cavnas parameter on the transferred context?
  How do you synchronize the main page setting canvas.width or
 canvas.height
  with the worker trying to render to it?
 
 
  *) Create a context directly in a Worker (or anywhere for that matter)
 
  As in var gl = new WebGLRenderingContext
 
  Pros:
 
  . ???
 
  Cons:
 
  . requires defining how the backbuffer size is set.
 Maybe there is no backbuffer for a directly created
  WebGLRenderingContext?
  . if there is no backbuffer then using one of these contexts to draw
 into a
  texture
or 2d context is problematic

 This alternative seems like the one that can be moved forward most
 easily, since essentially all of the changes would be within the WebGL
 spec.

  - Extend the spec to support context sharing. (Each
 WebGLRenderingContext points to an opaque WebGLContextGroup object.)
  - Define structured cloning semantics for WebGLContextGroup.
  - Add a constructor or factory method to WebGLRenderingContext
 allowing creation with a WebGLContextGroup. Contexts created in this
 manner would have no back buffer by default. (FBOs could still be used
 to do rendering with the context.)
  - Allow some or all of the WebGLObject types (textures, etc.) to be
 either copied during structured cloning or transferred.

 Then the worker can at least upload textures to the GPU completely
 asynchronously from the main thread, and inform the main thread via
 postMessage when they have finished uploading. That seems to be a
 tractable first step and one that would already have immediate
 benefits for developers.


That problem I have with this path is the cons mentioned above. It's a dead
end.

With real contexts you can do this

webglcontext1.texImage2D(..., webglcontext2.canvas);

and this

context2d.drawImage(webgl.canvas, ...)

But with a context created with new WebGLRenderingContext you can't do
anything like that because size of the backbuffer is not defined.
Eventually we'll want to support operation like that and we'll likely end
up with something like DrawingSurface or CanvasSurface or OffscreenCanvas.
At that point this ability to go new WebGLRenderingContext will just be
left over cruft.

Also we'll have to define how to addEventListner for WebGLRenderContext for
listening for lost context or for async context creation (yea, less
important on workers). That stuff is currently not on
WebGLRenderingContext. It seems like it should stay off if it.









 -Ken


  *) Create an offscreen canvas like object minus HTMLElement parts
 
  Pros:
 
  . same or nearly the API as already exists for canvas
  . flexible. getContext can return different kinds of context. Maybe only
  webgl for now?
 
  Cons:
 
  . ???
 
 
 
 



exposing CANVAS or something like it to Web Workers

2012-05-14 Thread
I'd like to work on exposing something like CANVAS to web workers.

Ideally how over it works I'd like to be able to

*) get a 2d context in a web worker
*) get a WebGL context in a web worker
*) download images in a web worker and the images with both 2d contexts and
WebGL contexts

Any thoughts?


Re: exposing CANVAS or something like it to Web Workers

2012-05-14 Thread
On Mon, May 14, 2012 at 4:42 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Mon, May 14, 2012 at 3:28 PM, Glenn Maynard gl...@zewt.org wrote:
  On Mon, May 14, 2012 at 3:01 PM, Gregg Tavares (勤) g...@google.com
  wrote:
 
  I'd like to work on exposing something like CANVAS to web workers.
 
  Ideally how over it works I'd like to be able to
 
  *) get a 2d context in a web worker
 
 
  I'd recommend not trying to tackle 2d and 3d contexts at once, and only
  worrying about WebGL to start.
 
  Another issue: rendering in a worker thread onto a canvas which is
 displayed
  in the main thread.  This needs to be solved in a way that doesn't cause
 the
  asynchronous nature of what's happening to be visible to scripts.
  toDataURL
  and toBlob would probably need to be prohibited on the canvas element.
  I'm
  not sure what the actual API would look like.

 If/when we do this, I think it should be done in such a way that the
 main window can't access the canvas object at all. Similar to what
 happens when an ArrayBuffer is transferred to a Worker using
 structured cloning. Once a canvas is transferred to a Worker, any
 access to it should throw or return null/0/. If you want to transfer
 pixel data to the main thread, it seems less racy to do that by
 getting the pixel data in the Worker which owns the canvas and then
 transfer that to the main thread using postMessage.


How about separating the canvasy parts of canvas from canvas and the imagy
parts of image from image.

In other words, Imagine canvas is implemented like this

class Canvas : public HTMLElement {
  private:
CanvasSurface* m_surface;  // everything about canvas that is not
HTMLElement
};

And that Image is similarly implemented as

class Image : public HTMLElement {
  private:
Picture* m_picture;  // everything about Image that is not HTMLElement
}

now imagine you can instantiate inner implementation of these things. The
parts that are not HTMLElement

var canvasSurface = new CanvasSurface();
var ctx = canvasSurface.getContext(2d);
var pic = new Picture;
pic.src = http://someplace.com/someimage.jpg;;
pic.onload = function() {
   ctx.drawImage(pic, 0, );
}

Let's assume you can instantiate these things in either the page or a
worker. Nether can be transfered.

Would that work? What problems would that have?






  This would also require some
  equivalent to requestAnimationFrame in the worker thread.

 Agreed!

 / Jonas



Re: exposing CANVAS or something like it to Web Workers

2012-05-14 Thread
On Mon, May 14, 2012 at 5:12 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 5/14/12 8:03 PM, Gregg Tavares (勤) wrote:

 var canvasSurface = new CanvasSurface();
 var ctx = canvasSurface.getContext(2d)**;
 var pic = new Picture;
 pic.src = 
 http://someplace.com/**someimage.jpghttp://someplace.com/someimage.jpg
 ;
 pic.onload = function() {
ctx.drawImage(pic, 0, );
 }

 Let's assume you can instantiate these things in either the page or a
 worker. Nether can be transfered.

 Would that work? What problems would that have?


 Two things that come to mind immediately:

 1)  Various canvas 2d context methods depend on the styles of the canvas
 to define how they actually behave.  Clearly this would need some sort of
 changes for Workers anyway; the question is what those changes would need
 to be.


Which methods are these?




 2)  How (or maybe whether) this should work with pic.src = 
 http://someplace.com/**someimage.svg http://someplace.com/someimage.svg
 is an interesting question.

 3)  This leaves open the question of how to get data from the worker back
 to the main thread to paint there.


I feel that's a somewhat orthogonal issue to getting a Canvas or
CanvasSurface in a worker. At least for the WebGL case, WebGL already
defines ways to share data safely between contexts so that use case is
already covered.

For a 2d context I can certainly imagine lots of ways. Some fast, some slow

slow) pass the result of toDataURL back

slow) pass an ImageData.data back (transfer of ownership)

fast) some how use a CanvasSurface as the source of a video tag

maybe there are some other ideas? But, even if we didn't resolve this, it's
still massively useful, at least for WebGL, to be able to instantiate a
WebGL context in a worker.






 #1 is an issue with any proposal that puts a 2d context in a worker.

 #2 is only an issue if we do the image loads in workers somehow; if we
 wanted to just rasterize the SVG and pass the resulting data to the worker
 there would be no problem, obviously.

 For #3, being able to transfer a canvas context from the page to a worker
 but leave it painting to the canvas may still be desirable...

 -Boris




Re: exposing CANVAS or something like it to Web Workers

2012-05-14 Thread
On Mon, May 14, 2012 at 6:07 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 5/14/12 8:55 PM, Gregg Tavares (勤) wrote:

1)  Various canvas 2d context methods depend on the styles of the
canvas to define how they actually behave.  Clearly this would need
some sort of changes for Workers anyway; the question is what those
changes would need to be.

 Which methods are these?


 Anything involving setting color (e.g. the strokeStyle setter, the
 fillStyle setter), due to currentColor.  Anything involving text because
 font styles come from the element or document.


Good to know.

That doesn't sound like a showstopper though. If a canvas/CanvasSurface is
available in workers the simplest solution would just be that
currentColor defaults to something black? or nothing . Pick one.



 Those are the ones that come to mind offhand, but I haven't looked at the
 various recent additions to the 2d context closely.

 -Boris



Re: exposing CANVAS or something like it to Web Workers

2012-05-14 Thread
On Mon, May 14, 2012 at 6:23 PM, Jonas Sicking jo...@sicking.cc wrote:

 On Mon, May 14, 2012 at 5:10 PM, Charles Pritchard ch...@jumis.com
 wrote:
  On May 14, 2012, at 4:42 PM, Jonas Sicking jo...@sicking.cc wrote:
 
  On Mon, May 14, 2012 at 3:28 PM, Glenn Maynard gl...@zewt.org wrote:
  On Mon, May 14, 2012 at 3:01 PM, Gregg Tavares (勤) g...@google.com
 wrote:
 
  I'd like to work on exposing something like CANVAS to web workers.
 
  Ideally how over it works I'd like to be able to
 
  *) get a 2d context in a web worker
 
 
  I'd recommend not trying to tackle 2d and 3d contexts at once, and only
  worrying about WebGL to start.
 
  Another issue: rendering in a worker thread onto a canvas which is
 displayed
  in the main thread.  This needs to be solved in a way that doesn't
 cause the
  asynchronous nature of what's happening to be visible to scripts.
  toDataURL
  and toBlob would probably need to be prohibited on the canvas element.
  I'm
  not sure what the actual API would look like.
 
  If/when we do this, I think it should be done in such a way that the
  main window can't access the canvas object at all. Similar to what
  happens when an ArrayBuffer is transferred to a Worker using
  structured cloning. Once a canvas is transferred to a Worker, any
  access to it should throw or return null/0/. If you want to transfer
  pixel data to the main thread, it seems less racy to do that by
  getting the pixel data in the Worker which owns the canvas and then
  transfer that to the main thread using postMessage.
 
  This would also require some
  equivalent to requestAnimationFrame in the worker thread.
 
  Agreed!
 
  / Jonas
 
 
 
  I'm a bit lost-- wouldn't we just postMessage from the document over to
 the web worker when we want a refresh?
 
  I agree that we ought to be transferring pixel data not Canvas contexts;
 with the possible exception of CSS context.
 
  We could just create new canvas instances inside the worker thread. I'd
 still prefer to clone CanvasPattern as a means of transferring paint over
 to the worker, though sending pixel data would work too.
 
  I heard Picture come up-- it seems like that object might have
 additional semantics for high resolution alternatives that may need to be
 considered.

 I was saying that I think we should transfer the context from the main
 thread to the worker thread. The worker thread should then be able to
 use the context to draw directly to the screen without interacting
 with the main thread.


That's a great goal but is transferring the right way to do it?

context.canvas is currently a reference to the canvas from which the
context as created. Will that just go NULL on transfer? Will it change to
some other object that is not a Canvas but acts similarly?

What happens to the context on the main page? All of it's methods become
no-ops and it's properties become non-live?

How will things synchronize if I call canvas.toDataURL after passing the
context to a work? Exception? nothing? It seems hard to define how that
would synchronize

If there was a way to allow a worker to generate a media stream and one of
those ways involves an in worker canvas/canvassurface, then it seems like
none of the above questions have to be answered. Instead the worker creates
the surface, and then through some other API attached it to a video tag.
You can call video.toDataURL, that's well defined (I assume)

Synchronization is also somewhat defined in that direction. Doesn't that
seem like the path of least resistance?






 You should generally not need to transfer pixel data. But I think it
 should be possible to grab pixel data on whichever thread is currently
 owning a context. This will implicitly make it possible to transfer
 pixel data if anyone wants to do it.

 / Jonas



Adding a paint event to HTMLElement to support Web Components / Shadow DOM

2012-05-08 Thread
Imagine you want to make a Web Component that draws a graph
Imagine that you'd like the graph to show more data if it's larger and less
if it's smaller. In other words, you don't want it to scale the data.
Imagine you set that component's size to width: 100%; height: 100% to scale
to its container

Question: How does the Web Component know when to repaint its content?

AFAICT the resize event only fires on window. If the point of Web
Components is to allow people to make self contained components it seems
like there might be the need for some way of letting the component know it
needs to repaint.

Resize is just one example.

Imagine a relatively heavy to repaint WebComponent like one that draws an
representation of an audio wave. If that component is hidden behind some
other component it would be nice if it didn't re-draw itself. When it
becomes visible thought needs  to know it should redraw itself.

Does a 'paint' event make sense?


Re: Adding a paint event to HTMLElement to support Web Components / Shadow DOM

2012-05-08 Thread
On Tue, May 8, 2012 at 5:56 PM, Boris Zbarsky bzbar...@mit.edu wrote:

 On 5/8/12 8:30 PM, Gregg Tavares (勤) wrote:

 AFAICT the resize event only fires on window.


 There have been proposals over the years to change that.


  Imagine a relatively heavy to repaint WebComponent like one that draws
 an representation of an audio wave. If that component is hidden behind
 some other component it would be nice if it didn't re-draw itself.


 This seems like a use case for requestAnimationFrame's second argument,
 and browser quality-of-implementation issues.


I don't think I understand how requestAnimationFrame would work here. Maybe
my example was poor. I'm not suggesting a live constantly updating audio
wave. Instead I'm suggesting a static WebComponent that is heavy to render.
For example the wave display in an audio editing tool. Let's say I had an
app that displayed several audio tracks, some of those tracks are scrolled
off the page. (like this http://www.newfreedownloads.com/imgs/17189-w520.jpg)
The tracks components are set to 100% width so that sizing the window ends
up re-sizing all the components, even the components off the screen.
Ideally only those components that are on the screen will get a paint event
since if say 80% of the components are off the screen and they are heavy to
update it would be nice if they weren't updated until the user brings them
on the screen by scrolling them on.




  Does a 'paint' event make sense?


 Possibly, depending on how it's defined; actually running arbitrary script
 during painting is pretty undesirable (e.g. ideally painting happens on a
 totally separate thread from script, and having to synchronize them is not
 particularly ideal).

 -Boris