blob: 20b09b98396a4165064372d3df86d29d38d5adda [file] [log] [blame]
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef Canvas2DLayerBridge_h
#define Canvas2DLayerBridge_h
#include "cc/layers/texture_layer_client.h"
#include "cc/resources/texture_mailbox.h"
#include "platform/PlatformExport.h"
#include "platform/geometry/IntSize.h"
#include "platform/graphics/ImageBufferSurface.h"
#include "platform/graphics/paint/PaintRecorder.h"
#include "platform/graphics/paint/PaintSurface.h"
#include "public/platform/WebExternalTextureLayer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/color_space.h"
#include "wtf/Allocator.h"
#include "wtf/Deque.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
#include "wtf/Vector.h"
#include "wtf/WeakPtr.h"
#include <memory>
class SkImage;
struct SkImageInfo;
namespace gpu {
namespace gles2 {
class GLES2Interface;
}
}
namespace blink {
class Canvas2DLayerBridgeTest;
class ImageBuffer;
class WebGraphicsContext3DProvider;
class SharedContextRateLimiter;
#if OS(MACOSX)
// Canvas hibernation is currently disabled on MacOS X due to a bug that causes
// content loss. TODO: Find a better fix for crbug.com/588434
#define CANVAS2D_HIBERNATION_ENABLED 0
// IOSurfaces are a primitive only present on OS X.
#define USE_IOSURFACE_FOR_2D_CANVAS 1
#else
#define CANVAS2D_HIBERNATION_ENABLED 1
#define USE_IOSURFACE_FOR_2D_CANVAS 0
#endif
// TODO: Fix background rendering and remove this workaround. crbug.com/600386
#define CANVAS2D_BACKGROUND_RENDER_SWITCH_TO_CPU 0
class PLATFORM_EXPORT Canvas2DLayerBridge
: public NON_EXPORTED_BASE(cc::TextureLayerClient),
public RefCounted<Canvas2DLayerBridge> {
WTF_MAKE_NONCOPYABLE(Canvas2DLayerBridge);
public:
enum AccelerationMode {
DisableAcceleration,
EnableAcceleration,
ForceAccelerationForTesting,
};
Canvas2DLayerBridge(std::unique_ptr<WebGraphicsContext3DProvider>,
const IntSize&,
int msaaSampleCount,
OpacityMode,
AccelerationMode,
const gfx::ColorSpace&,
bool skSurfacesUseColorSpace,
SkColorType);
~Canvas2DLayerBridge() override;
// cc::TextureLayerClient implementation.
bool PrepareTextureMailbox(
cc::TextureMailbox* outMailbox,
std::unique_ptr<cc::SingleReleaseCallback>* outReleaseCallback) override;
// Callback for mailboxes given to the compositor from PrepareTextureMailbox.
void mailboxReleased(const gpu::Mailbox&,
const gpu::SyncToken&,
bool lostResource);
// ImageBufferSurface implementation
void finalizeFrame();
void doPaintInvalidation(const FloatRect& dirtyRect);
void willWritePixels();
void willOverwriteAllPixels();
void willOverwriteCanvas();
PaintCanvas* canvas();
void disableDeferral(DisableDeferralReason);
bool checkSurfaceValid();
bool restoreSurface();
WebLayer* layer() const;
bool isAccelerated() const;
void setFilterQuality(SkFilterQuality);
void setIsHidden(bool);
void setImageBuffer(ImageBuffer*);
void didDraw(const FloatRect&);
bool writePixels(const SkImageInfo&,
const void* pixels,
size_t rowBytes,
int x,
int y);
void flush();
void flushGpu();
bool isHidden() { return m_isHidden; }
OpacityMode opacityMode() { return m_opacityMode; }
void dontUseIdleSchedulingForTesting() {
m_dontUseIdleSchedulingForTesting = true;
}
void beginDestruction();
void hibernate();
bool isHibernating() const { return m_hibernationImage.get(); }
sk_sp<SkColorSpace> skSurfaceColorSpace() const;
SkColorType colorType() const { return m_colorType; }
bool hasRecordedDrawCommands() { return m_haveRecordedDrawCommands; }
sk_sp<SkImage> newImageSnapshot(AccelerationHint, SnapshotReason);
// The values of the enum entries must not change because they are used for
// usage metrics histograms. New values can be added to the end.
enum HibernationEvent {
HibernationScheduled = 0,
HibernationAbortedDueToDestructionWhileHibernatePending = 1,
HibernationAbortedDueToPendingDestruction = 2,
HibernationAbortedDueToVisibilityChange = 3,
HibernationAbortedDueGpuContextLoss = 4,
HibernationAbortedDueToSwitchToUnacceleratedRendering = 5,
HibernationAbortedDueToAllocationFailure = 6,
HibernationEndedNormally = 7,
HibernationEndedWithSwitchToBackgroundRendering = 8,
HibernationEndedWithFallbackToSW = 9,
HibernationEndedWithTeardown = 10,
HibernationAbortedBecauseNoSurface = 11,
HibernationEventCount = 12,
};
class PLATFORM_EXPORT Logger {
public:
virtual void reportHibernationEvent(HibernationEvent);
virtual void didStartHibernating() {}
virtual ~Logger() {}
};
void setLoggerForTesting(std::unique_ptr<Logger>);
private:
#if USE_IOSURFACE_FOR_2D_CANVAS
// All information associated with a CHROMIUM image.
struct ImageInfo;
#endif // USE_IOSURFACE_FOR_2D_CANVAS
struct MailboxInfo {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
gpu::Mailbox m_mailbox;
sk_sp<SkImage> m_image;
RefPtr<Canvas2DLayerBridge> m_parentLayerBridge;
#if USE_IOSURFACE_FOR_2D_CANVAS
// If this mailbox wraps an IOSurface-backed texture, the ids of the
// CHROMIUM image and the texture.
RefPtr<ImageInfo> m_imageInfo;
#endif // USE_IOSURFACE_FOR_2D_CANVAS
MailboxInfo(const MailboxInfo&);
MailboxInfo();
};
gpu::gles2::GLES2Interface* contextGL();
void startRecording();
void skipQueuedDrawCommands();
void flushRecordingOnly();
void reportSurfaceCreationFailure();
PaintSurface* getOrCreateSurface(AccelerationHint = PreferAcceleration);
bool shouldAccelerate(AccelerationHint) const;
// Returns the GL filter associated with |m_filterQuality|.
GLenum getGLFilter();
#if USE_IOSURFACE_FOR_2D_CANVAS
// Creates an IOSurface-backed texture. Copies |image| into the texture.
// Prepares a mailbox from the texture. The caller must have created a new
// MailboxInfo, and prepended it to |m_mailboxs|. Returns whether the
// mailbox was successfully prepared. |mailbox| is an out parameter only
// populated on success.
bool prepareIOSurfaceMailboxFromImage(SkImage*, cc::TextureMailbox*);
// Creates an IOSurface-backed texture. Returns an ImageInfo, which is empty
// on failure. The caller takes ownership of both the texture and the image.
RefPtr<ImageInfo> createIOSurfaceBackedTexture();
// Releases all resources associated with a CHROMIUM image.
void deleteCHROMIUMImage(RefPtr<ImageInfo>);
// Releases all resources in the CHROMIUM image cache.
void clearCHROMIUMImageCache();
#endif // USE_IOSURFACE_FOR_2D_CANVAS
// Prepends a new MailboxInfo object to |m_mailboxes|.
void createMailboxInfo();
// Returns whether the mailbox was successfully prepared from the SkImage.
// The mailbox is an out parameter only populated on success.
bool prepareMailboxFromImage(sk_sp<SkImage>, cc::TextureMailbox*);
// Resets Skia's texture bindings. This method should be called after
// changing texture bindings.
void resetSkiaTextureBinding();
std::unique_ptr<PaintRecorder> m_recorder;
sk_sp<PaintSurface> m_surface;
sk_sp<SkImage> m_hibernationImage;
int m_initialSurfaceSaveCount;
std::unique_ptr<WebExternalTextureLayer> m_layer;
std::unique_ptr<WebGraphicsContext3DProvider> m_contextProvider;
std::unique_ptr<SharedContextRateLimiter> m_rateLimiter;
std::unique_ptr<Logger> m_logger;
WeakPtrFactory<Canvas2DLayerBridge> m_weakPtrFactory;
ImageBuffer* m_imageBuffer;
int m_msaaSampleCount;
int m_framesSinceLastCommit = 0;
size_t m_bytesAllocated;
bool m_haveRecordedDrawCommands;
bool m_destructionInProgress;
SkFilterQuality m_filterQuality;
bool m_isHidden;
bool m_isDeferralEnabled;
bool m_softwareRenderingWhileHidden;
bool m_surfaceCreationFailedAtLeastOnce = false;
bool m_hibernationScheduled = false;
bool m_dontUseIdleSchedulingForTesting = false;
bool m_didDrawSinceLastFlush = false;
bool m_didDrawSinceLastGpuFlush = false;
friend class Canvas2DLayerBridgeTest;
friend class CanvasRenderingContext2DTest;
friend class HTMLCanvasPainterTestForSPv2;
uint32_t m_lastImageId;
enum {
// We should normally not have more that two active mailboxes at a time,
// but sometimes we may have three due to the async nature of mailbox
// handling.
MaxActiveMailboxes = 3,
};
Deque<MailboxInfo, MaxActiveMailboxes> m_mailboxes;
GLenum m_lastFilter;
AccelerationMode m_accelerationMode;
OpacityMode m_opacityMode;
const IntSize m_size;
// The color space that the compositor is to use. This will always be
// defined.
gfx::ColorSpace m_colorSpace;
bool m_skSurfacesUseColorSpace = false;
SkColorType m_colorType;
int m_recordingPixelCount;
#if USE_IOSURFACE_FOR_2D_CANVAS
// Each element in this vector represents an IOSurface backed texture that
// is ready to be reused.
// Elements in this vector can safely be purged in low memory conditions.
Vector<RefPtr<ImageInfo>> m_imageInfoCache;
#endif // USE_IOSURFACE_FOR_2D_CANVAS
};
} // namespace blink
#endif