[Public WebGL] using the same context with multiple canvases

Gregg Tavares (社用) [email protected]
Wed Dec 19 00:01:26 PST 2012


On Wed, Dec 19, 2012 at 4:36 PM, Gregg Tavares (社用) <[email protected]> wrote:

> Let me try to be clearer with a more concrete proposal.
>
> Canvas and CanvasProxy is great. You pass a CanvasProxy to a worker.
> You now have some object with some loose connection to the canvas in the
> page.
>
> This is what i think I would be a good and consistent api
>
> CanvasProxy has the same API as Canvas (minus the HTMLElement parts)
>
> that includes
>
>    getContext
>    toDataURL
>
> and being able to pass one to CanvasRenderingContext::drawImage,
> WebGLRenderingContext::teximage2D etc...
>
> For the simple case that works just like the current API. You pass a
> CanvasProxy to the worker and the call getContext on it (with optional
> creation parameters just like getContext today)
>
> For multiple canvases with 1 context you use the Drawingbuffer method
> (pick name) both in and out of workers.
>
> main page JS example
>
>    var canvas1 = document.createElement("canvas1");
>    var canvas2 = document.createElement("canvas2");
>
>    var db1 = new Drawingbuffer({..params..};
>    var db2 = new Drawingbuffer({..params..};
>
>    canvas1.setDrawingbuffer(db1);
>    canvas2.setDrawingbuffer(db2);
>
>    var gl = new WebGLRenderingContext();
>    gl.bindDrawingbuffer(db1);
>    gl.drawXXX();
>    g.bindDrawingbuffer(db2);
>    gl.drawXXX();
>
> worker example with Canvases from main page
>
>    var proxy1 = .... // some CanvasProxy passed from the page
>    var proxy2 = .... // some CanvasProxy passed from the page
>
>    var db1 = new Drawingbuffer({..params..};
>    var db2 = new Drawingbuffer({..params..};
>
>    proxy1.setDrawingbuffer(db1);
>    proxy2.setDrawingbuffer(db2);
>
>    var gl = new WebGLRenderingContext();
>    gl.bindDrawingbuffer(db1);
>    gl.drawXXX();
>    g.bindDrawingbuffer(db2);
>    gl.drawXXX();
>
> some worker with no canvaes
>
>    var db1 = new Drawingbuffer({..params..};
>    var db2 = new Drawingbuffer({..params..};
>
>    var gl = new WebGLRenderingContext();
>    gl.bindDrawingbuffer(db1);
>    gl.drawXXX();
>    g.bindDrawingbuffer(db2);
>    gl.drawXXX();
>
> Ideally these would all work with canvas2d as well.
> There are examples of libraries that can switch renderers
> Three.js <https://github.com/mrdoob/three.js/> comes to mind. There are
> also examples of libraries
> that emulate canvas 2d on WebGL to get extra benefits
> (like being able to apply special effects) webgl-2d.js<https://github.com/corbanbrook/webgl-2d>.
> It just
> seems like it would be really nice if they could treat all this
> stuff the same regardless of 2d or WebGL context.
>
>
Doh, I hit send before i was finished. Examples with canvas2d

   var canvas1 = document.createElement("canvas1");
   var canvas2 = document.createElement("canvas2");

   var db1 = new Drawingbuffer({..params..};
   var db2 = new Drawingbuffer({..params..};

   canvas1.setDrawingbuffer(db1);
   canvas2.setDrawingbuffer(db2);

   var ctx = new CanvasRenderingContext();
   ctx.setDrawingbuffer(db1);
   ctx.fillRect(...);
   ctx.setDrawingbuffer(db2);
   ctx.fillRect(...);

worker example with Canvases from main page

   var proxy1 = .... // some CanvasProxy passed from the page
   var proxy2 = .... // some CanvasProxy passed from the page

   var db1 = new Drawingbuffer({..params..};
   var db2 = new Drawingbuffer({..params..};

   proxy1.setDrawingbuffer(db1);
   proxy2.setDrawingbuffer(db2);

   var ctx = new CanvasRenderingContext();
   ctx.setDrawingbuffer(db1);
   ctx.fillRect(...);
   ctx.setDrawingbuffer(db2);
   ctx.fillRect(...);

some worker with no canvases

   var db1 = new Drawingbuffer({..params..};
   var db2 = new Drawingbuffer({..params..};

   var ctx = new CanvasRenderingContext();
   ctx.setDrawingbuffer(db1);
   ctx.fillRect(...);
   ctx.setDrawingbuffer(db2);
   ctx.fillRect(...);

Why not have the consistency? This solution seems consistent
and also has the benefit of allowing creation parameters for
canvas 2d once we convince the powers that be that they're
needed :-)

as for commit(), it seems to me it should go on DrawingBuffer as
that's the object that's deciding if something is swapping buffers
on commit or copying buffers on commit.

Having it on Drawingbuffer also means it can be used in workers
without a canvas.

It also suggests it can be used outside workers
which some people have asked for to let them choose
when they are ready to present their work.  Example:

    // in main page.
    var canvas = document.createElement("canvas");
    var db = new Drawingbuffer({implicitCommit: false});
    canvas.setDrawingBuffer(db);
    var ctx = new CanvasRenderingContext();
    ctx.setDrawingBuffer(db);

    // Draw something that takes a while in steps
    // Don't present it until it's finished.
    var stepsToGo = 100;
    var processNextStep = function() {
      // draw more stuff
     ...
      --stepsToGo;
      if (stepsToGo < 0) {
        db.commit();
        return;
      }
      setTimeout(processNextStep, 100);
   };

This is something you can't do with the current implicit commit

One last thing. Drawingbuffer should be passable anywhere canvas is
as in being able to pass one to CanvasRenderingContext::drawImage,
WebGLRenderingContext::teximage2D etc...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://khronos.org/pipermail/public_webgl_khronos.org/attachments/20121219/580c3a52/attachment.html>


More information about the public_webgl mailing list