b031a37fd9136a4c24c8a809b558936aae5f3b5e
[platform/framework/web/crosswalk-tizen.git] /
1 /*
2  * Copyright (c) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #ifndef DrawingBuffer_h
32 #define DrawingBuffer_h
33
34 #include "cc/layers/texture_layer_client.h"
35 #include "gpu/command_buffer/common/mailbox.h"
36 #include "gpu/command_buffer/common/sync_token.h"
37 #include "platform/PlatformExport.h"
38 #include "platform/geometry/IntSize.h"
39 #include "platform/graphics/GraphicsTypes3D.h"
40 #include "platform/graphics/gpu/WebGLImageConversion.h"
41 #include "third_party/khronos/GLES2/gl2.h"
42 #include "third_party/skia/include/core/SkBitmap.h"
43 #include "wtf/Deque.h"
44 #include "wtf/Noncopyable.h"
45 #include "wtf/RefCounted.h"
46 #include "wtf/Vector.h"
47 #include <memory>
48
49 namespace cc {
50 class SharedBitmap;
51 }
52
53 namespace gpu {
54 namespace gles2 {
55 class GLES2Interface;
56 }
57 }
58
59 namespace WTF {
60 class ArrayBufferContents;
61 }
62
63 namespace blink {
64 class Extensions3DUtil;
65 class StaticBitmapImage;
66 class WebExternalTextureLayer;
67 class WebGraphicsContext3DProvider;
68 class WebGraphicsContext3DProviderWrapper;
69 class WebLayer;
70
71 // Manages a rendering target (framebuffer + attachment) for a canvas.  Can
72 // publish its rendering results to a WebLayer for compositing.
73 class PLATFORM_EXPORT DrawingBuffer
74     : public NON_EXPORTED_BASE(cc::TextureLayerClient),
75       public RefCounted<DrawingBuffer> {
76   WTF_MAKE_NONCOPYABLE(DrawingBuffer);
77
78  public:
79   class Client {
80    public:
81     // Returns true if the DrawingBuffer is currently bound for draw.
82     virtual bool DrawingBufferClientIsBoundForDraw() = 0;
83     virtual void DrawingBufferClientRestoreScissorTest() = 0;
84     // Restores the mask and clear value for color, depth, and stencil buffers.
85     virtual void DrawingBufferClientRestoreMaskAndClearValues() = 0;
86     virtual void DrawingBufferClientRestorePixelPackAlignment() = 0;
87     // Restores the GL_TEXTURE_2D binding for the active texture unit only.
88     virtual void DrawingBufferClientRestoreTexture2DBinding() = 0;
89     virtual void DrawingBufferClientRestoreRenderbufferBinding() = 0;
90     virtual void DrawingBufferClientRestoreFramebufferBinding() = 0;
91     virtual void DrawingBufferClientRestorePixelUnpackBufferBinding() = 0;
92   };
93
94   enum PreserveDrawingBuffer {
95     Preserve,
96     Discard,
97   };
98   enum WebGLVersion {
99     WebGL1,
100     WebGL2,
101   };
102
103   enum ChromiumImageUsage {
104     AllowChromiumImage,
105     DisallowChromiumImage,
106   };
107
108   static PassRefPtr<DrawingBuffer> create(
109       std::unique_ptr<WebGraphicsContext3DProvider>,
110       Client*,
111       const IntSize&,
112       bool premultipliedAlpha,
113       bool wantAlphaChannel,
114       bool wantDepthBuffer,
115       bool wantStencilBuffer,
116       bool wantAntialiasing,
117       PreserveDrawingBuffer,
118       WebGLVersion,
119       ChromiumImageUsage);
120   static void forceNextDrawingBufferCreationToFail();
121
122   ~DrawingBuffer() override;
123
124   // Destruction will be completed after all mailboxes are released.
125   void beginDestruction();
126
127   // Issues a glClear() on all framebuffers associated with this DrawingBuffer.
128   void clearFramebuffers(GLbitfield clearMask);
129
130   // Indicates whether the DrawingBuffer internally allocated a packed
131   // depth-stencil renderbuffer in the situation where the end user only asked
132   // for a depth buffer. In this case, we need to upgrade clears of the depth
133   // buffer to clears of the depth and stencil buffers in order to avoid
134   // performance problems on some GPUs.
135   bool hasImplicitStencilBuffer() const { return m_hasImplicitStencilBuffer; }
136   bool hasDepthBuffer() const { return !!m_depthStencilBuffer; }
137   bool hasStencilBuffer() const { return !!m_depthStencilBuffer; }
138
139   // Given the desired buffer size, provides the largest dimensions that will
140   // fit in the pixel budget.
141   static IntSize adjustSize(const IntSize& desiredSize,
142                             const IntSize& curSize,
143                             int maxTextureSize);
144
145   // Resizes (or allocates if necessary) all buffers attached to the default
146   // framebuffer. Returns whether the operation was successful.
147   bool resize(const IntSize&);
148
149   // Bind the default framebuffer to |target|. |target| must be
150   // GL_FRAMEBUFFER, GL_READ_FRAMEBUFFER, or GL_DRAW_FRAMEBUFFER.
151   void bind(GLenum target);
152   IntSize size() const { return m_size; }
153
154   // Resolves the multisample color buffer to the normal color buffer and leaves
155   // the resolved color buffer bound to GL_READ_FRAMEBUFFER and
156   // GL_DRAW_FRAMEBUFFER.
157   void resolveAndBindForReadAndDraw();
158
159   bool multisample() const;
160
161   bool discardFramebufferSupported() const {
162     return m_discardFramebufferSupported;
163   }
164
165   void markContentsChanged();
166   void setBufferClearNeeded(bool);
167   bool bufferClearNeeded() const;
168   void setIsHidden(bool);
169   void setFilterQuality(SkFilterQuality);
170
171   // Whether the target for draw operations has format GL_RGBA, but is
172   // emulating format GL_RGB. When the target's storage is first
173   // allocated, its alpha channel must be cleared to 1. All future drawing
174   // operations must use a color mask with alpha=GL_FALSE.
175   bool requiresAlphaChannelToBePreserved();
176
177   // Similar to requiresAlphaChannelToBePreserved(), but always targets the
178   // default framebuffer.
179   bool defaultBufferRequiresAlphaChannelToBePreserved();
180
181   WebLayer* platformLayer();
182
183   gpu::gles2::GLES2Interface* contextGL();
184   WebGraphicsContext3DProvider* contextProvider();
185
186   // cc::TextureLayerClient implementation.
187   bool PrepareTextureMailbox(
188       cc::TextureMailbox* outMailbox,
189       std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) override;
190
191   // Returns a StaticBitmapImage backed by a texture containing the current
192   // contents of the front buffer. This is done without any pixel copies. The
193   // texture in the ImageBitmap is from the active ContextProvider on the
194   // DrawingBuffer.
195   PassRefPtr<StaticBitmapImage> transferToStaticBitmapImage();
196
197   bool copyToPlatformTexture(gpu::gles2::GLES2Interface*,
198                              GLuint texture,
199                              GLenum internalFormat,
200                              GLenum destType,
201                              GLint level,
202                              bool premultiplyAlpha,
203                              bool flipY,
204                              const IntPoint& destTextureOffset,
205                              const IntRect& sourceSubRectangle,
206                              SourceDrawingBuffer);
207
208   bool paintRenderingResultsToImageData(int&,
209                                         int&,
210                                         SourceDrawingBuffer,
211                                         WTF::ArrayBufferContents&);
212
213   int sampleCount() const { return m_sampleCount; }
214   bool explicitResolveOfMultisampleData() const {
215     return m_antiAliasingMode == MSAAExplicitResolve;
216   }
217
218   // Rebind the read and draw framebuffers that WebGL is expecting.
219   void restoreFramebufferBindings();
220
221   // Restore all state that may have been dirtied by any call.
222   void restoreAllState();
223
224   void addNewMailboxCallback(std::unique_ptr<WTF::Closure> closure) {
225     m_newMailboxCallback = std::move(closure);
226   }
227
228  protected:  // For unittests
229   DrawingBuffer(std::unique_ptr<WebGraphicsContext3DProvider>,
230                 std::unique_ptr<Extensions3DUtil>,
231                 Client*,
232                 bool discardFramebufferSupported,
233                 bool wantAlphaChannel,
234                 bool premultipliedAlpha,
235                 PreserveDrawingBuffer,
236                 WebGLVersion,
237                 bool wantsDepth,
238                 bool wantsStencil,
239                 ChromiumImageUsage);
240
241   bool initialize(const IntSize&, bool useMultisampling);
242
243   // Shared memory bitmaps that were released by the compositor and can be used
244   // again by this DrawingBuffer.
245   struct RecycledBitmap {
246     std::unique_ptr<cc::SharedBitmap> bitmap;
247     IntSize size;
248   };
249   Vector<RecycledBitmap> m_recycledBitmaps;
250
251  private:
252   friend class ScopedStateRestorer;
253   friend class ColorBuffer;
254
255   // This structure should wrap all public entrypoints that may modify GL state.
256   // It will restore all state when it drops out of scope.
257   class ScopedStateRestorer {
258    public:
259     ScopedStateRestorer(DrawingBuffer*);
260     ~ScopedStateRestorer();
261
262     // Mark parts of the state that are dirty and need to be restored.
263     void setClearStateDirty() { m_clearStateDirty = true; }
264     void setPixelPackAlignmentDirty() { m_pixelPackAlignmentDirty = true; }
265     void setTextureBindingDirty() { m_textureBindingDirty = true; }
266     void setRenderbufferBindingDirty() { m_renderbufferBindingDirty = true; }
267     void setFramebufferBindingDirty() { m_framebufferBindingDirty = true; }
268     void setPixelUnpackBufferBindingDirty() {
269       m_pixelUnpackBufferBindingDirty = true;
270     }
271
272    private:
273     RefPtr<DrawingBuffer> m_drawingBuffer;
274     // The previous state restorer, in case restorers are nested.
275     ScopedStateRestorer* m_previousStateRestorer = nullptr;
276     bool m_clearStateDirty = false;
277     bool m_pixelPackAlignmentDirty = false;
278     bool m_textureBindingDirty = false;
279     bool m_renderbufferBindingDirty = false;
280     bool m_framebufferBindingDirty = false;
281     bool m_pixelUnpackBufferBindingDirty = false;
282   };
283
284   // All parameters necessary to generate the texture for the ColorBuffer.
285   struct ColorBufferParameters {
286     DISALLOW_NEW();
287     GLenum target = 0;
288     GLenum internalColorFormat = 0;
289
290     // The internal color format used when allocating storage for the
291     // texture. This may be different from internalColorFormat if RGB
292     // emulation is required.
293     GLenum creationInternalColorFormat = 0;
294     GLenum colorFormat = 0;
295   };
296
297   struct ColorBuffer : public RefCounted<ColorBuffer> {
298     ColorBuffer(DrawingBuffer*,
299                 const ColorBufferParameters&,
300                 const IntSize&,
301                 GLuint textureId,
302                 GLuint imageId);
303     ~ColorBuffer();
304
305     // The owning DrawingBuffer. Note that DrawingBuffer is explicitly destroyed
306     // by the beginDestruction method, which will eventually drain all of its
307     // ColorBuffers.
308     RefPtr<DrawingBuffer> drawingBuffer;
309
310     const ColorBufferParameters parameters;
311     const IntSize size;
312
313     const GLuint textureId = 0;
314     const GLuint imageId = 0;
315
316     // The mailbox used to send this buffer to the compositor.
317     gpu::Mailbox mailbox;
318
319     // The sync token for when this buffer was sent to the compositor.
320     gpu::SyncToken produceSyncToken;
321
322     // The sync token for when this buffer was received back from the
323     // compositor.
324     gpu::SyncToken receiveSyncToken;
325
326    private:
327     WTF_MAKE_NONCOPYABLE(ColorBuffer);
328   };
329
330   // The same as clearFramebuffers(), but leaves GL state dirty.
331   void clearFramebuffersInternal(GLbitfield clearMask);
332
333   // The same as reset(), but leaves GL state dirty.
334   bool resizeFramebufferInternal(const IntSize&);
335
336   // The same as commit(), but leaves GL state dirty.
337   void resolveMultisampleFramebufferInternal();
338
339   bool prepareTextureMailboxInternal(
340       cc::TextureMailbox* outMailbox,
341       std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback,
342       bool forceGpuResult);
343
344   // Helper functions to be called only by prepareTextureMailboxInternal.
345   bool finishPrepareTextureMailboxGpu(
346       cc::TextureMailbox* outMailbox,
347       std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback);
348   bool finishPrepareTextureMailboxSoftware(
349       cc::TextureMailbox* outMailbox,
350       std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback);
351
352   // Callbacks for mailboxes given to the compositor from
353   // finishPrepareTextureMailboxGpu and finishPrepareTextureMailboxSoftware.
354   void mailboxReleasedGpu(RefPtr<ColorBuffer>,
355                           const gpu::SyncToken&,
356                           bool lostResource);
357   void mailboxReleasedSoftware(std::unique_ptr<cc::SharedBitmap>,
358                                const IntSize&,
359                                const gpu::SyncToken&,
360                                bool lostResource);
361
362   // The texture parameters to use for a texture that will be backed by a
363   // CHROMIUM_image, backed by a GpuMemoryBuffer.
364   ColorBufferParameters gpuMemoryBufferColorBufferParameters();
365
366   // The texture parameters to use for an ordinary GL texture.
367   ColorBufferParameters textureColorBufferParameters();
368
369   // Attempts to allocator storage for, or resize all buffers. Returns whether
370   // the operation was successful.
371   bool resizeDefaultFramebuffer(const IntSize&);
372
373   void clearPlatformLayer();
374
375   std::unique_ptr<cc::SharedBitmap> createOrRecycleBitmap();
376
377   // Updates the current size of the buffer, ensuring that
378   // s_currentResourceUsePixels is updated.
379   void setSize(const IntSize& size);
380
381   // This is the order of bytes to use when doing a readback.
382   enum ReadbackOrder { ReadbackRGBA, ReadbackSkia };
383
384   // Helper function which does a readback from the currently-bound
385   // framebuffer into a buffer of a certain size with 4-byte pixels.
386   void readBackFramebuffer(unsigned char* pixels,
387                            int width,
388                            int height,
389                            ReadbackOrder,
390                            WebGLImageConversion::AlphaOp);
391
392   // Helper function to flip a bitmap vertically.
393   void flipVertically(uint8_t* data, int width, int height);
394
395   // If RGB emulation is required, then the CHROMIUM image's alpha channel
396   // must be immediately cleared after it is bound to a texture. Nothing
397   // should be allowed to change the alpha channel after this.
398   void clearChromiumImageAlpha(const ColorBuffer&);
399
400   // Tries to create a CHROMIUM_image backed texture if
401   // RuntimeEnabledFeatures::webGLImageChromiumEnabled() is true. On failure,
402   // or if the flag is false, creates a default texture. Always returns a valid
403   // ColorBuffer.
404   RefPtr<ColorBuffer> createColorBuffer(const IntSize&);
405
406   // Creates or recycles a ColorBuffer of size |m_size|.
407   PassRefPtr<ColorBuffer> createOrRecycleColorBuffer();
408
409   // Attaches |m_backColorBuffer| to |m_fbo|, which is always the source for
410   // read operations.
411   void attachColorBufferToReadFramebuffer();
412
413   // Whether the WebGL client desires an explicit resolve. This is
414   // implemented by forwarding all draw operations to a multisample
415   // renderbuffer, which is resolved before any read operations or swaps.
416   bool wantExplicitResolve();
417
418   // Whether the WebGL client wants a depth or stencil buffer.
419   bool wantDepthOrStencil();
420
421   // The format to use when creating a multisampled renderbuffer.
422   GLenum getMultisampledRenderbufferFormat();
423
424   // Weak, reset by beginDestruction.
425   Client* m_client = nullptr;
426
427   const PreserveDrawingBuffer m_preserveDrawingBuffer;
428   const WebGLVersion m_webGLVersion;
429
430   std::unique_ptr<WebGraphicsContext3DProviderWrapper> m_contextProvider;
431   // Lifetime is tied to the m_contextProvider.
432   gpu::gles2::GLES2Interface* m_gl;
433   std::unique_ptr<Extensions3DUtil> m_extensionsUtil;
434   IntSize m_size = {-1, -1};
435   const bool m_discardFramebufferSupported;
436   const bool m_wantAlphaChannel;
437   const bool m_premultipliedAlpha;
438   const bool m_softwareRendering;
439   bool m_hasImplicitStencilBuffer = false;
440   bool m_storageTextureSupported = false;
441
442   std::unique_ptr<WTF::Closure> m_newMailboxCallback;
443
444   // The current state restorer, which is used to track state dirtying. It is in
445   // error to dirty state shared with WebGL while there is no existing state
446   // restorer. It is also in error to instantiate two state restorers at once.
447   ScopedStateRestorer* m_stateRestorer = nullptr;
448
449   // This is used when the user requests either a depth or stencil buffer.
450   GLuint m_depthStencilBuffer = 0;
451
452   // When wantExplicitResolve() returns true, the target of all draw
453   // operations.
454   GLuint m_multisampleFBO = 0;
455
456   // The id of the renderbuffer storage for |m_multisampleFBO|.
457   GLuint m_multisampleRenderbuffer = 0;
458
459   // When wantExplicitResolve() returns false, the target of all draw and
460   // read operations. When wantExplicitResolve() returns true, the target of
461   // all read operations.
462   GLuint m_fbo = 0;
463
464   // The ColorBuffer that backs |m_fbo|.
465   RefPtr<ColorBuffer> m_backColorBuffer;
466
467   // The ColorBuffer that was most recently presented to the compositor by
468   // prepareTextureMailboxInternal.
469   RefPtr<ColorBuffer> m_frontColorBuffer;
470
471   // True if our contents have been modified since the last presentation of this
472   // buffer.
473   bool m_contentsChanged = true;
474
475   // True if commit() has been called since the last time markContentsChanged()
476   // had been called.
477   bool m_contentsChangeCommitted = false;
478   bool m_bufferClearNeeded = false;
479
480   // Whether the client wants a depth or stencil buffer.
481   const bool m_wantDepth;
482   const bool m_wantStencil;
483
484   enum AntialiasingMode {
485     None,
486     MSAAImplicitResolve,
487     MSAAExplicitResolve,
488     ScreenSpaceAntialiasing,
489   };
490
491   AntialiasingMode m_antiAliasingMode = None;
492
493   int m_maxTextureSize = 0;
494   int m_sampleCount = 0;
495   bool m_destructionInProgress = false;
496   bool m_isHidden = false;
497   SkFilterQuality m_filterQuality = kLow_SkFilterQuality;
498
499   std::unique_ptr<WebExternalTextureLayer> m_layer;
500
501   // Mailboxes that were released by the compositor can be used again by this
502   // DrawingBuffer.
503   Deque<RefPtr<ColorBuffer>> m_recycledColorBufferQueue;
504
505   // If the width and height of the Canvas's backing store don't
506   // match those that we were given in the most recent call to
507   // reshape(), then we need an intermediate bitmap to read back the
508   // frame buffer into. This seems to happen when CSS styles are
509   // used to resize the Canvas.
510   SkBitmap m_resizingBitmap;
511
512   // In the case of OffscreenCanvas, we do not want to enable the
513   // WebGLImageChromium flag, so we replace all the
514   // RuntimeEnabledFeatures::webGLImageChromiumEnabled() call with
515   // shouldUseChromiumImage() calls, and set m_chromiumImageUsage to
516   // DisallowChromiumImage in the case of OffscreenCanvas.
517   ChromiumImageUsage m_chromiumImageUsage;
518   bool shouldUseChromiumImage();
519 };
520
521 }  // namespace blink
522
523 #endif  // DrawingBuffer_h