2 * Copyright (c) 2010, Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
31 #ifndef DrawingBuffer_h
32 #define DrawingBuffer_h
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"
60 class ArrayBufferContents;
64 class Extensions3DUtil;
65 class StaticBitmapImage;
66 class WebExternalTextureLayer;
67 class WebGraphicsContext3DProvider;
68 class WebGraphicsContext3DProviderWrapper;
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);
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;
94 enum PreserveDrawingBuffer {
103 enum ChromiumImageUsage {
105 DisallowChromiumImage,
108 static PassRefPtr<DrawingBuffer> create(
109 std::unique_ptr<WebGraphicsContext3DProvider>,
112 bool premultipliedAlpha,
113 bool wantAlphaChannel,
114 bool wantDepthBuffer,
115 bool wantStencilBuffer,
116 bool wantAntialiasing,
117 PreserveDrawingBuffer,
120 static void forceNextDrawingBufferCreationToFail();
122 ~DrawingBuffer() override;
124 // Destruction will be completed after all mailboxes are released.
125 void beginDestruction();
127 // Issues a glClear() on all framebuffers associated with this DrawingBuffer.
128 void clearFramebuffers(GLbitfield clearMask);
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; }
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,
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&);
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; }
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();
159 bool multisample() const;
161 bool discardFramebufferSupported() const {
162 return m_discardFramebufferSupported;
165 void markContentsChanged();
166 void setBufferClearNeeded(bool);
167 bool bufferClearNeeded() const;
168 void setIsHidden(bool);
169 void setFilterQuality(SkFilterQuality);
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();
177 // Similar to requiresAlphaChannelToBePreserved(), but always targets the
178 // default framebuffer.
179 bool defaultBufferRequiresAlphaChannelToBePreserved();
181 WebLayer* platformLayer();
183 gpu::gles2::GLES2Interface* contextGL();
184 WebGraphicsContext3DProvider* contextProvider();
186 // cc::TextureLayerClient implementation.
187 bool PrepareTextureMailbox(
188 cc::TextureMailbox* outMailbox,
189 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) override;
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
195 PassRefPtr<StaticBitmapImage> transferToStaticBitmapImage();
197 bool copyToPlatformTexture(gpu::gles2::GLES2Interface*,
199 GLenum internalFormat,
202 bool premultiplyAlpha,
204 const IntPoint& destTextureOffset,
205 const IntRect& sourceSubRectangle,
206 SourceDrawingBuffer);
208 bool paintRenderingResultsToImageData(int&,
211 WTF::ArrayBufferContents&);
213 int sampleCount() const { return m_sampleCount; }
214 bool explicitResolveOfMultisampleData() const {
215 return m_antiAliasingMode == MSAAExplicitResolve;
218 // Rebind the read and draw framebuffers that WebGL is expecting.
219 void restoreFramebufferBindings();
221 // Restore all state that may have been dirtied by any call.
222 void restoreAllState();
224 void addNewMailboxCallback(std::unique_ptr<WTF::Closure> closure) {
225 m_newMailboxCallback = std::move(closure);
228 protected: // For unittests
229 DrawingBuffer(std::unique_ptr<WebGraphicsContext3DProvider>,
230 std::unique_ptr<Extensions3DUtil>,
232 bool discardFramebufferSupported,
233 bool wantAlphaChannel,
234 bool premultipliedAlpha,
235 PreserveDrawingBuffer,
241 bool initialize(const IntSize&, bool useMultisampling);
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;
249 Vector<RecycledBitmap> m_recycledBitmaps;
252 friend class ScopedStateRestorer;
253 friend class ColorBuffer;
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 {
259 ScopedStateRestorer(DrawingBuffer*);
260 ~ScopedStateRestorer();
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;
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;
284 // All parameters necessary to generate the texture for the ColorBuffer.
285 struct ColorBufferParameters {
288 GLenum internalColorFormat = 0;
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;
297 struct ColorBuffer : public RefCounted<ColorBuffer> {
298 ColorBuffer(DrawingBuffer*,
299 const ColorBufferParameters&,
305 // The owning DrawingBuffer. Note that DrawingBuffer is explicitly destroyed
306 // by the beginDestruction method, which will eventually drain all of its
308 RefPtr<DrawingBuffer> drawingBuffer;
310 const ColorBufferParameters parameters;
313 const GLuint textureId = 0;
314 const GLuint imageId = 0;
316 // The mailbox used to send this buffer to the compositor.
317 gpu::Mailbox mailbox;
319 // The sync token for when this buffer was sent to the compositor.
320 gpu::SyncToken produceSyncToken;
322 // The sync token for when this buffer was received back from the
324 gpu::SyncToken receiveSyncToken;
327 WTF_MAKE_NONCOPYABLE(ColorBuffer);
330 // The same as clearFramebuffers(), but leaves GL state dirty.
331 void clearFramebuffersInternal(GLbitfield clearMask);
333 // The same as reset(), but leaves GL state dirty.
334 bool resizeFramebufferInternal(const IntSize&);
336 // The same as commit(), but leaves GL state dirty.
337 void resolveMultisampleFramebufferInternal();
339 bool prepareTextureMailboxInternal(
340 cc::TextureMailbox* outMailbox,
341 std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback,
342 bool forceGpuResult);
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);
352 // Callbacks for mailboxes given to the compositor from
353 // finishPrepareTextureMailboxGpu and finishPrepareTextureMailboxSoftware.
354 void mailboxReleasedGpu(RefPtr<ColorBuffer>,
355 const gpu::SyncToken&,
357 void mailboxReleasedSoftware(std::unique_ptr<cc::SharedBitmap>,
359 const gpu::SyncToken&,
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();
366 // The texture parameters to use for an ordinary GL texture.
367 ColorBufferParameters textureColorBufferParameters();
369 // Attempts to allocator storage for, or resize all buffers. Returns whether
370 // the operation was successful.
371 bool resizeDefaultFramebuffer(const IntSize&);
373 void clearPlatformLayer();
375 std::unique_ptr<cc::SharedBitmap> createOrRecycleBitmap();
377 // Updates the current size of the buffer, ensuring that
378 // s_currentResourceUsePixels is updated.
379 void setSize(const IntSize& size);
381 // This is the order of bytes to use when doing a readback.
382 enum ReadbackOrder { ReadbackRGBA, ReadbackSkia };
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,
390 WebGLImageConversion::AlphaOp);
392 // Helper function to flip a bitmap vertically.
393 void flipVertically(uint8_t* data, int width, int height);
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&);
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
404 RefPtr<ColorBuffer> createColorBuffer(const IntSize&);
406 // Creates or recycles a ColorBuffer of size |m_size|.
407 PassRefPtr<ColorBuffer> createOrRecycleColorBuffer();
409 // Attaches |m_backColorBuffer| to |m_fbo|, which is always the source for
411 void attachColorBufferToReadFramebuffer();
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();
418 // Whether the WebGL client wants a depth or stencil buffer.
419 bool wantDepthOrStencil();
421 // The format to use when creating a multisampled renderbuffer.
422 GLenum getMultisampledRenderbufferFormat();
424 // Weak, reset by beginDestruction.
425 Client* m_client = nullptr;
427 const PreserveDrawingBuffer m_preserveDrawingBuffer;
428 const WebGLVersion m_webGLVersion;
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;
442 std::unique_ptr<WTF::Closure> m_newMailboxCallback;
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;
449 // This is used when the user requests either a depth or stencil buffer.
450 GLuint m_depthStencilBuffer = 0;
452 // When wantExplicitResolve() returns true, the target of all draw
454 GLuint m_multisampleFBO = 0;
456 // The id of the renderbuffer storage for |m_multisampleFBO|.
457 GLuint m_multisampleRenderbuffer = 0;
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.
464 // The ColorBuffer that backs |m_fbo|.
465 RefPtr<ColorBuffer> m_backColorBuffer;
467 // The ColorBuffer that was most recently presented to the compositor by
468 // prepareTextureMailboxInternal.
469 RefPtr<ColorBuffer> m_frontColorBuffer;
471 // True if our contents have been modified since the last presentation of this
473 bool m_contentsChanged = true;
475 // True if commit() has been called since the last time markContentsChanged()
477 bool m_contentsChangeCommitted = false;
478 bool m_bufferClearNeeded = false;
480 // Whether the client wants a depth or stencil buffer.
481 const bool m_wantDepth;
482 const bool m_wantStencil;
484 enum AntialiasingMode {
488 ScreenSpaceAntialiasing,
491 AntialiasingMode m_antiAliasingMode = None;
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;
499 std::unique_ptr<WebExternalTextureLayer> m_layer;
501 // Mailboxes that were released by the compositor can be used again by this
503 Deque<RefPtr<ColorBuffer>> m_recycledColorBufferQueue;
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;
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();
523 #endif // DrawingBuffer_h