[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Updating the Spec W.R.T. preserveDrawingBuffer = false

I don't think it's so unreasonable the way it is, but I can see the benefit in allowing for screenshotting.

However, it would pull things out of line with what readPixels will give you back. This is also potentially non-trivial on Firefox OS. 

Why do devs not just use pDB=true if they need this functionality? If they really do need the bit of extra perf (which should be quite uncommon), why not add an option to do a screenshotting frame render?

I can see this making life easier for some, but I believe it may prove to be a headache to implement in some cases, where most apps can use pDB, and the rest can do their own screenshotting?


----- Original Message -----
From: "Kenneth Russell" <kbr@google.com>
To: "Gregg Tavares" <gman@google.com>
Cc: "public webgl" <public_webgl@khronos.org>, "Dean Jackson" <dino@apple.com>
Sent: Monday, June 10, 2013 5:28:32 PM
Subject: Re: [Public WebGL] Updating the Spec W.R.T. preserveDrawingBuffer = false

This change would make life much simpler for developers. The request
comes from the Google Maps and Feedback teams, so is motivated by
real-world applications and libraries.

For background, preserveDrawingBuffer=false was intended to reduce
memory bandwidth on WebGL implementations on mobile devices (tiled
architectures in particular) using EXT_discard_framebuffer and similar
extensions. The idea is that when the current WebGL frame is handed to
the web page compositor, DiscardFramebufferEXT is called. The rendered
output is then only available to the web page compositor; the
application no longer has access to it.

iOS's EAGLContext [1], CAEAGLLayer [2], and EAGLDrawable [3] also
informed the design of preserveDrawingBuffer=false. The goal was to
allow kEAGLDrawablePropertyRetainedBacking to be set to NO on the
layer backing the WebGL-rendered canvas.

This proposed preserveDrawingBuffer change probably would not decrease
WebGL's efficiency in the majority of browsers and on the majority of
OSs. The browser can still use DiscardFramebufferEXT for the depth and
stencil buffers when presenting the WebGL canvas to the compositor. In
my understanding, it's never been possible to discard the color
buffer, because the page compositor needs it in case the page needs to
be redrawn using the same WebGL results from the previous frame. Since
the color buffer is always available after compositing, it can be made
available to toDataURL and other APIs at no cost.

It looks to me like the only outstanding question is whether this
change to preserveDrawingBuffer=false would eliminate an important
optimization opportunity on iOS. Questions for Apple:

(1) Does the WebGL implementation in iAds use
kEAGLDrawablePropertyRetainedBacking=NO for WebGL? In particular, if
the web page compositor needs to redraw the page and display the last
frame's WebGL results, does that work?

(2) What about (potential) printing of WebGL content in Safari for
iOS? Would that work with kEAGLDrawablePropertyRetainedBacking=NO?

Do other WebGL implementers have feedback on the proposal?



[1] http://developer.apple.com/library/ios/#documentation/opengles/reference/EAGLContext_ClassRef/Reference/EAGLContext.html
[2] http://developer.apple.com/library/ios/#documentation/QuartzCore/Reference/CAEAGLLayer_Class/CAEGLLayer/CAEGLLayer.html
[3] http://developer.apple.com/library/ios/#documentation/iPhone/Reference/EAGLDrawable_Ref/EAGLDrawable/EAGLDrawable.html

On Fri, Jun 7, 2013 at 12:05 AM, Gregg Tavares <gman@google.com> wrote:
> I think we should revisit or maybe just clarify the spec with regards to
> what happens when you call a function that uses the contents of a canvas.
> The specific functions are
>   canvas.toDataURL
>   context2d.drawImage(canvas, ...);
>   gl.texImage2D(...., canvas)
>   gl.texSubImage2D(..., canvas);
> The current text of the spec says
> WebGL presents its drawing buffer to the HTML page compositor immediately
> before a compositing operation, but only if clear, drawArrays or
> drawElements have been called since the last compositing operation, while
> the drawing buffer is the currently bound framebuffer. Before the drawing
> buffer is presented for compositing the implementation shall ensure that all
> rendering operations have been flushed to the drawing buffer. By default,
> after compositing the contents of the drawing buffer shall be cleared to
> their default values, as shown in the table above.
> This default behavior can be changed by setting the preserveDrawingBuffer
> attribute of the WebGLContextAttributes object. If this flag is true, the
> contents of the drawing buffer shall be preserved until the author either
> clears or overwrites them. If this flag is false, attempting to perform
> operations using this context as a source image after the rendering function
> has returned can lead to undefined behavior. This includes readPixels or
> toDataURL calls, or using this context as the source image of another
> context's texImage2D or drawImage call.
> I'd like to suggest it does not make a lot of scene to have this undefined.
> Specifically I think toDataURL, drawImage and texImage2D should change so
> that until drawing commands are issued after a composite the pixels being
> composited will be used.
> It seems strange that I can fill a canvas with pixels. Once filled with
> pixels I can transform it, rotate it, move it around in the DOM. I can even
> print it. But if I ask what's in it with one of those 4 functions it will
> tell me "0,0,0,0"
> To be more specific I'm suggesting every canvas effectively has a
> "drawing_buffer_to_copy_from" reference to a DrawingBuffer. When a draw
> command is issued "drawing_buffer_to_copy_from" is set to the DrawingBuffer
> being drawn to. (the back buffer)
> If preserveDrawingBuffer = false then when compositing happens conceptually
> DrawingBuffers are swapped. "drawing_buffer_to_copy_from" is NOT updated to
> point to the new buffer (it's only updated by calling a drawing function).
> This means until a drawing function is called,
> toDataURL/drawImage/texImage2D would give the contents of the canvas.
> readPixels on the other hand always gives data from the current
> DrawingBuffer so its behavior would not change. The DrawingBuffers are
> swapped at composite time. readPixels always reads from the current
> DrawingBuffer (backbuffer).
> It seems like this would make more intuitive sense. If I see a canvas on the
> screen with an image in and I use it with one of those 4 functions I'll get
> what I see.
> This would also enable screenshot apis to work with WebGL. Currently they
> can't work without co-operation from the app. For example this one
> https://github.com/niklasvh/html2canvas
> Thoughts?

You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email:
unsubscribe public_webgl

You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email:
unsubscribe public_webgl