From 7ce0501a7e169e8c647ca6787d4fdcb7ab4d91da Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Mon, 13 Jul 2015 22:17:23 -0700 Subject: [PATCH] Remove some unneeded DEPS from //sky We no longer actually need to depend on this code. It's cleaner if we don't list these dependencies. TBR=eseidel@google.com Review URL: https://codereview.chromium.org/1229113003 . --- engine/bindings/BUILD.gn | 4 - engine/core/BUILD.gn | 5 - engine/core/script/dart_controller.h | 2 +- engine/platform/BUILD.gn | 17 - .../graphics/Canvas2DImageBufferSurface.h | 73 - .../platform/graphics/Canvas2DLayerBridge.cpp | 573 ------ .../platform/graphics/Canvas2DLayerBridge.h | 145 -- .../graphics/Canvas2DLayerManager.cpp | 141 -- .../platform/graphics/Canvas2DLayerManager.h | 67 - engine/platform/graphics/GraphicsContext.cpp | 9 - engine/platform/graphics/GraphicsTypes3D.h | 61 - engine/platform/graphics/ImageBuffer.cpp | 73 - engine/platform/graphics/ImageBuffer.h | 13 - engine/platform/graphics/ImageBufferSurface.h | 2 - .../platform/graphics/gpu/DrawingBuffer.cpp | 1049 ---------- engine/platform/graphics/gpu/DrawingBuffer.h | 305 --- .../graphics/gpu/DrawingBufferTest.cpp | 678 ------- .../graphics/gpu/Extensions3DUtil.cpp | 95 - .../platform/graphics/gpu/Extensions3DUtil.h | 42 - .../graphics/gpu/WebGLImageBufferSurface.cpp | 78 - .../graphics/gpu/WebGLImageBufferSurface.h | 69 - .../graphics/gpu/WebGLImageConversion.cpp | 1778 ----------------- .../graphics/gpu/WebGLImageConversion.h | 168 -- 23 files changed, 1 insertion(+), 5446 deletions(-) delete mode 100644 engine/platform/graphics/Canvas2DImageBufferSurface.h delete mode 100644 engine/platform/graphics/Canvas2DLayerBridge.cpp delete mode 100644 engine/platform/graphics/Canvas2DLayerBridge.h delete mode 100644 engine/platform/graphics/Canvas2DLayerManager.cpp delete mode 100644 engine/platform/graphics/Canvas2DLayerManager.h delete mode 100644 engine/platform/graphics/GraphicsTypes3D.h delete mode 100644 engine/platform/graphics/gpu/DrawingBuffer.cpp delete mode 100644 engine/platform/graphics/gpu/DrawingBuffer.h delete mode 100644 engine/platform/graphics/gpu/DrawingBufferTest.cpp delete mode 100644 engine/platform/graphics/gpu/Extensions3DUtil.cpp delete mode 100644 engine/platform/graphics/gpu/Extensions3DUtil.h delete mode 100644 engine/platform/graphics/gpu/WebGLImageBufferSurface.cpp delete mode 100644 engine/platform/graphics/gpu/WebGLImageBufferSurface.h delete mode 100644 engine/platform/graphics/gpu/WebGLImageConversion.cpp delete mode 100644 engine/platform/graphics/gpu/WebGLImageConversion.h diff --git a/engine/bindings/BUILD.gn b/engine/bindings/BUILD.gn index 742d9b8ef..d929fb7e5 100644 --- a/engine/bindings/BUILD.gn +++ b/engine/bindings/BUILD.gn @@ -378,7 +378,6 @@ source_set("generated_bindings") { "//base", "//dart/runtime:libdart", "//dart/runtime/vm:libdart_platform", - "//gpu/command_buffer/client:gles2_c_lib", "//mojo/application", "//mojo/common", "//mojo/public/c/system", @@ -386,9 +385,6 @@ source_set("generated_bindings") { "//mojo/public/cpp/system", "//mojo/public/cpp/utility", "//mojo/public/interfaces/application", - "//mojo/services/keyboard/public/interfaces", - "//mojo/services/navigation/public/interfaces", - "//mojo/services/view_manager/public/cpp", "//skia", "//sky/engine/core:core_names", "//sky/engine/wtf", diff --git a/engine/core/BUILD.gn b/engine/core/BUILD.gn index f3b42e480..0cd1329a5 100644 --- a/engine/core/BUILD.gn +++ b/engine/core/BUILD.gn @@ -13,7 +13,6 @@ rel_sky_core_gen_dir = rebase_path(sky_core_output_dir, root_build_dir) source_set("libraries") { public_deps = [ "//base", - "//gpu/command_buffer/client:gles2_c_lib", "//mojo/application", "//mojo/common", "//mojo/public/c/system", @@ -21,10 +20,6 @@ source_set("libraries") { "//mojo/public/cpp/system", "//mojo/public/cpp/utility", "//mojo/public/interfaces/application", - "//mojo/services/keyboard/public/interfaces", - "//mojo/services/navigation/public/interfaces", - "//mojo/services/network/public/interfaces", - "//mojo/services/view_manager/public/cpp", "//skia", "//sky/engine/tonic:tonic", "//sky/engine/wtf", diff --git a/engine/core/script/dart_controller.h b/engine/core/script/dart_controller.h index 9b464341b..ece380ec3 100644 --- a/engine/core/script/dart_controller.h +++ b/engine/core/script/dart_controller.h @@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "dart/runtime/include/dart_api.h" -#include "mojo/services/network/public/interfaces/url_loader.mojom.h" +#include "mojo/public/cpp/system/data_pipe.h" #include "sky/engine/wtf/OwnPtr.h" #include "sky/engine/wtf/text/AtomicString.h" #include "sky/engine/wtf/text/TextPosition.h" diff --git a/engine/platform/BUILD.gn b/engine/platform/BUILD.gn index 1b838bc82..54dc25afb 100644 --- a/engine/platform/BUILD.gn +++ b/engine/platform/BUILD.gn @@ -295,11 +295,6 @@ source_set("platform") { "geometry/TransformState.h", "graphics/BitmapImage.cpp", "graphics/BitmapImage.h", - "graphics/Canvas2DImageBufferSurface.h", - "graphics/Canvas2DLayerBridge.cpp", - "graphics/Canvas2DLayerBridge.h", - "graphics/Canvas2DLayerManager.cpp", - "graphics/Canvas2DLayerManager.h", "graphics/Color.cpp", "graphics/Color.h", "graphics/ColorSpace.cpp", @@ -330,7 +325,6 @@ source_set("platform") { "graphics/GraphicsContextStateSaver.h", "graphics/GraphicsTypes.cpp", "graphics/GraphicsTypes.h", - "graphics/GraphicsTypes3D.h", "graphics/Image.cpp", "graphics/Image.h", "graphics/ImageBuffer.cpp", @@ -420,14 +414,6 @@ source_set("platform") { "graphics/filters/SourceGraphic.h", "graphics/filters/SpotLightSource.cpp", "graphics/filters/SpotLightSource.h", - "graphics/gpu/DrawingBuffer.cpp", - "graphics/gpu/DrawingBuffer.h", - "graphics/gpu/Extensions3DUtil.cpp", - "graphics/gpu/Extensions3DUtil.h", - "graphics/gpu/WebGLImageBufferSurface.cpp", - "graphics/gpu/WebGLImageBufferSurface.h", - "graphics/gpu/WebGLImageConversion.cpp", - "graphics/gpu/WebGLImageConversion.h", "graphics/skia/GaneshUtils.cpp", "graphics/skia/GaneshUtils.h", "graphics/skia/NativeImageSkia.cpp", @@ -584,7 +570,6 @@ source_set("platform") { deps = [ ":make_platform_generated", "//base:base", - "//gpu/command_buffer/client:gles2_c_lib", "//mojo/application", "//mojo/common", "//mojo/environment:chromium", @@ -606,7 +591,6 @@ source_set("platform") { ] forward_dependent_configs_from = [ - "//gpu/command_buffer/client:gles2_c_lib", "//skia", "//third_party:jpeg", "//third_party/iccjpeg", @@ -666,7 +650,6 @@ test("platform_unittests") { "geometry/RoundedRectTest.cpp", "graphics/GraphicsContextTest.cpp", "graphics/ThreadSafeDataTransportTest.cpp", - "graphics/gpu/DrawingBufferTest.cpp", "image-decoders/ImageDecoderTest.cpp", "mac/ScrollElasticityControllerTest.mm", "network/HTTPParsersTest.cpp", diff --git a/engine/platform/graphics/Canvas2DImageBufferSurface.h b/engine/platform/graphics/Canvas2DImageBufferSurface.h deleted file mode 100644 index 40471ea2e..000000000 --- a/engine/platform/graphics/Canvas2DImageBufferSurface.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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 SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DIMAGEBUFFERSURFACE_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DIMAGEBUFFERSURFACE_H_ - -#include "sky/engine/platform/graphics/Canvas2DLayerBridge.h" -#include "sky/engine/platform/graphics/ImageBufferSurface.h" - -namespace blink { - -// This shim necessary because ImageBufferSurfaces are not allowed to be RefCounted -class Canvas2DImageBufferSurface final : public ImageBufferSurface { -public: - Canvas2DImageBufferSurface(const IntSize& size, OpacityMode opacityMode = NonOpaque, int msaaSampleCount = 1) - : ImageBufferSurface(size, opacityMode) - , m_layerBridge(Canvas2DLayerBridge::create(size, opacityMode, msaaSampleCount)) - { - clear(); - } - - virtual ~Canvas2DImageBufferSurface() - { - if (m_layerBridge) - m_layerBridge->beginDestruction(); - } - - // ImageBufferSurface implementation - virtual void finalizeFrame() override { m_layerBridge->finalizeFrame(); } - virtual void willAccessPixels() override { m_layerBridge->willAccessPixels(); } - virtual SkCanvas* canvas() const override { return m_layerBridge->canvas(); } - virtual bool isValid() const override { return m_layerBridge && m_layerBridge->checkSurfaceValid(); } - virtual bool restore() override { return m_layerBridge->restoreSurface(); } - virtual WebLayer* layer() const override { return m_layerBridge->layer(); } - virtual Platform3DObject getBackingTexture() const override { return m_layerBridge->getBackingTexture(); } - virtual bool isAccelerated() const override { return m_layerBridge->isAccelerated(); } - virtual void setIsHidden(bool hidden) override { m_layerBridge->setIsHidden(hidden); } - virtual void setImageBuffer(ImageBuffer* imageBuffer) override { m_layerBridge->setImageBuffer(imageBuffer); } - -private: - RefPtr m_layerBridge; -}; - -} // namespace blink - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DIMAGEBUFFERSURFACE_H_ diff --git a/engine/platform/graphics/Canvas2DLayerBridge.cpp b/engine/platform/graphics/Canvas2DLayerBridge.cpp deleted file mode 100644 index 7a2cabc8a..000000000 --- a/engine/platform/graphics/Canvas2DLayerBridge.cpp +++ /dev/null @@ -1,573 +0,0 @@ -/* - * 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. - */ - - -#include "sky/engine/platform/graphics/Canvas2DLayerBridge.h" - -#include "sky/engine/platform/TraceEvent.h" -#include "sky/engine/platform/graphics/Canvas2DLayerManager.h" -#include "sky/engine/platform/graphics/ImageBuffer.h" -#include "sky/engine/public/platform/Platform.h" -#include "sky/engine/public/platform/WebGraphicsContext3D.h" -#include "sky/engine/public/platform/WebGraphicsContext3DProvider.h" -#include "sky/engine/wtf/RefCountedLeakCounter.h" -#include "third_party/skia/include/core/SkDevice.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/gpu/GrContext.h" - -namespace { -enum { - InvalidMailboxIndex = -1, -}; - -DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstanceCounter, ("Canvas2DLayerBridge")); -} - -namespace blink { - -static PassRefPtr createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount = 0) -{ - if (!gr) - return nullptr; - gr->resetContext(); - SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); - SkSurfaceProps disableLCDProps(0, kUnknown_SkPixelGeometry); - return adoptRef(SkSurface::NewRenderTarget(gr, SkSurface::kNo_Budgeted, info, msaaSampleCount, &disableLCDProps)); -} - -PassRefPtr Canvas2DLayerBridge::create(const IntSize& size, OpacityMode opacityMode, int msaaSampleCount) -{ - TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_SCOPE_NAME_PROCESS); - OwnPtr contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); - if (!contextProvider) - return nullptr; - RefPtr surface(createSkSurface(contextProvider->grContext(), size, msaaSampleCount)); - if (!surface) - return nullptr; - RefPtr layerBridge; - OwnPtr canvas = adoptPtr(SkDeferredCanvas::Create(surface.get())); - layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), canvas.release(), surface.release(), msaaSampleCount, opacityMode)); - return layerBridge.release(); -} - -Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr contextProvider, PassOwnPtr canvas, PassRefPtr surface, int msaaSampleCount, OpacityMode opacityMode) - : m_canvas(canvas) - , m_surface(surface) - , m_contextProvider(contextProvider) - , m_imageBuffer(0) - , m_msaaSampleCount(msaaSampleCount) - , m_bytesAllocated(0) - , m_didRecordDrawCommand(false) - , m_isSurfaceValid(true) - , m_framesPending(0) - , m_framesSinceMailboxRelease(0) - , m_destructionInProgress(false) - , m_rateLimitingEnabled(false) - , m_isHidden(false) - , m_next(0) - , m_prev(0) - , m_lastImageId(0) - , m_releasedMailboxInfoIndex(InvalidMailboxIndex) -{ - ASSERT(m_canvas); - ASSERT(m_surface); - ASSERT(m_contextProvider); - // Used by browser tests to detect the use of a Canvas2DLayerBridge. - TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_SCOPE_NAME_PROCESS); - m_layer = nullptr; - CRASH(); // No compositor. - m_layer->setOpaque(opacityMode == Opaque); - m_layer->setBlendBackgroundColor(opacityMode != Opaque); - m_layer->setRateLimitContext(m_rateLimitingEnabled); - m_canvas->setNotificationClient(this); -#ifndef NDEBUG - canvas2DLayerBridgeInstanceCounter.increment(); -#endif -} - -Canvas2DLayerBridge::~Canvas2DLayerBridge() -{ - ASSERT(m_destructionInProgress); - ASSERT(!Canvas2DLayerManager::get().isInList(this)); - m_layer.clear(); - freeReleasedMailbox(); -#if ENABLE(ASSERT) - Vector::iterator mailboxInfo; - for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) { - ASSERT(mailboxInfo->m_status != MailboxInUse); - ASSERT(mailboxInfo->m_status != MailboxReleased || m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid); - } -#endif - m_mailboxes.clear(); -#ifndef NDEBUG - canvas2DLayerBridgeInstanceCounter.decrement(); -#endif -} - -void Canvas2DLayerBridge::beginDestruction() -{ - ASSERT(!m_destructionInProgress); - setRateLimitingEnabled(false); - m_canvas->silentFlush(); - m_imageBuffer = 0; - freeTransientResources(); - setIsHidden(true); - m_destructionInProgress = true; - m_canvas->setNotificationClient(0); - m_surface.clear(); - m_canvas.clear(); - m_layer->clearTexture(); - // Orphaning the layer is required to trigger the recration of a new layer - // in the case where destruction is caused by a canvas resize. Test: - // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html - m_layer->layer()->removeFromParent(); - // To anyone who ever hits this assert: Please update crbug.com/344666 - // with repro steps. - ASSERT(!m_bytesAllocated); -} - -void Canvas2DLayerBridge::setIsHidden(bool hidden) -{ - ASSERT(!m_destructionInProgress); - bool newHiddenValue = hidden || m_destructionInProgress; - if (m_isHidden == newHiddenValue) - return; - - m_isHidden = newHiddenValue; - if (isHidden()) { - freeTransientResources(); - } -} - -void Canvas2DLayerBridge::willAccessPixels() -{ - // A readback operation may alter the texture parameters, which may affect - // the compositor's behavior. Therefore, we must trigger copy-on-write - // even though we are not technically writing to the texture, only to its - // parameters. - m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode); -} - -void Canvas2DLayerBridge::freeTransientResources() -{ - ASSERT(!m_destructionInProgress); - if (!m_isSurfaceValid) - return; - freeReleasedMailbox(); - flush(); - freeMemoryIfPossible(bytesAllocated()); - ASSERT(!hasTransientResources()); -} - -bool Canvas2DLayerBridge::hasTransientResources() const -{ - return !m_destructionInProgress && (hasReleasedMailbox() || bytesAllocated()); -} - -void Canvas2DLayerBridge::limitPendingFrames() -{ - ASSERT(!m_destructionInProgress); - if (isHidden()) { - freeTransientResources(); - return; - } - if (m_didRecordDrawCommand) { - m_framesPending++; - m_didRecordDrawCommand = false; - if (m_framesPending > 1) { - // Turn on the rate limiter if this layer tends to accumulate a - // non-discardable multi-frame backlog of draw commands. - setRateLimitingEnabled(true); - } - if (m_rateLimitingEnabled) { - flush(); - } - } - ++m_framesSinceMailboxRelease; - if (releasedMailboxHasExpired()) { - freeReleasedMailbox(); - } -} - -void Canvas2DLayerBridge::prepareForDraw() -{ - ASSERT(!m_destructionInProgress); - ASSERT(m_layer); - if (!checkSurfaceValid()) { - if (m_canvas) { - // drop pending commands because there is no surface to draw to - m_canvas->silentFlush(); - } - return; - } -} - -void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAllocated) -{ - ASSERT(!m_destructionInProgress); - intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated; - m_bytesAllocated = bytesAllocated; - Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, delta); -} - -size_t Canvas2DLayerBridge::storageAllocatedForRecording() -{ - return m_canvas->storageAllocatedForRecording(); -} - -void Canvas2DLayerBridge::flushedDrawCommands() -{ - ASSERT(!m_destructionInProgress); - storageAllocatedForRecordingChanged(storageAllocatedForRecording()); - m_framesPending = 0; -} - -void Canvas2DLayerBridge::skippedPendingDrawCommands() -{ - ASSERT(!m_destructionInProgress); - // Stop triggering the rate limiter if SkDeferredCanvas is detecting - // and optimizing overdraw. - setRateLimitingEnabled(false); - flushedDrawCommands(); -} - -void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled) -{ - ASSERT(!m_destructionInProgress); - if (m_rateLimitingEnabled != enabled) { - m_rateLimitingEnabled = enabled; - m_layer->setRateLimitContext(m_rateLimitingEnabled); - } -} - -size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) -{ - ASSERT(!m_destructionInProgress); - size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree); - m_bytesAllocated -= bytesFreed; - if (bytesFreed) - Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, -((intptr_t)bytesFreed)); - return bytesFreed; -} - -void Canvas2DLayerBridge::flush() -{ - ASSERT(!m_destructionInProgress); - if (m_canvas->hasPendingCommands()) { - TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush"); - freeReleasedMailbox(); // To avoid unnecessary triple-buffering - m_canvas->flush(); - } -} - -bool Canvas2DLayerBridge::releasedMailboxHasExpired() -{ - // This heuristic indicates that the canvas is not being - // actively presented by the compositor (3 frames rendered since - // last mailbox release), suggesting that double buffering is not required. - return hasReleasedMailbox() && m_framesSinceMailboxRelease > 2; -} - -Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::releasedMailboxInfo() -{ - return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0; -} - -bool Canvas2DLayerBridge::hasReleasedMailbox() const -{ - return m_releasedMailboxInfoIndex != InvalidMailboxIndex; -} - -void Canvas2DLayerBridge::freeReleasedMailbox() -{ - if (!m_isSurfaceValid || m_contextProvider->context3d()->isContextLost()) - return; - MailboxInfo* mailboxInfo = releasedMailboxInfo(); - if (!mailboxInfo) - return; - - ASSERT(mailboxInfo->m_status == MailboxReleased); - if (mailboxInfo->m_mailbox.syncPoint) { - context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); - mailboxInfo->m_mailbox.syncPoint = 0; - } - // Invalidate texture state in case the compositor altered it since the copy-on-write. - if (mailboxInfo->m_image) { - mailboxInfo->m_image->getTexture()->textureParamsModified(); - mailboxInfo->m_image.clear(); - } - mailboxInfo->m_status = MailboxAvailable; - m_releasedMailboxInfoIndex = InvalidMailboxIndex; - Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); -} - -WebGraphicsContext3D* Canvas2DLayerBridge::context() -{ - // Check on m_layer is necessary because context() may be called during - // the destruction of m_layer - if (m_layer && !m_destructionInProgress) - checkSurfaceValid(); // To ensure rate limiter is disabled if context is lost. - return m_contextProvider ? m_contextProvider->context3d() : 0; -} - -bool Canvas2DLayerBridge::checkSurfaceValid() -{ - ASSERT(!m_destructionInProgress); - if (m_destructionInProgress || !m_isSurfaceValid) - return false; - if (m_contextProvider->context3d()->isContextLost()) { - m_isSurfaceValid = false; - m_surface.clear(); - if (m_imageBuffer) - m_imageBuffer->notifySurfaceInvalid(); - setRateLimitingEnabled(false); - } - return m_isSurfaceValid; -} - -bool Canvas2DLayerBridge::restoreSurface() -{ - ASSERT(!m_destructionInProgress); - if (m_destructionInProgress) - return false; - ASSERT(m_layer && !m_isSurfaceValid); - - WebGraphicsContext3D* sharedContext = 0; - // We must clear the mailboxes before calling m_layer->clearTexture() to prevent - // re-entry via mailboxReleased from operating on defunct GrContext objects. - m_mailboxes.clear(); - m_releasedMailboxInfoIndex = InvalidMailboxIndex; - m_layer->clearTexture(); - m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); - if (m_contextProvider) - sharedContext = m_contextProvider->context3d(); - - if (sharedContext && !sharedContext->isContextLost()) { - IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height()); - RefPtr surface(createSkSurface(m_contextProvider->grContext(), size, m_msaaSampleCount)); - if (surface.get()) { - m_surface = surface.release(); - m_canvas->setSurface(m_surface.get()); - m_isSurfaceValid = true; - // FIXME: draw sad canvas picture into new buffer crbug.com/243842 - } - } - - return m_isSurfaceValid; -} - -bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap) -{ - if (m_destructionInProgress) { - // It can be hit in the following sequence. - // 1. Canvas draws something. - // 2. The compositor begins the frame. - // 3. Javascript makes a context be lost. - // 4. Here. - return false; - } - if (bitmap) { - // Using accelerated 2d canvas with software renderer, which - // should only happen in tests that use fake graphics contexts - // or in Android WebView in software mode. In this case, we do - // not care about producing any results for this canvas. - m_canvas->silentFlush(); - m_lastImageId = 0; - return false; - } - if (!checkSurfaceValid()) - return false; - - WebGraphicsContext3D* webContext = context(); - - // Release to skia textures that were previouosly released by the - // compositor. We do this before acquiring the next snapshot in - // order to cap maximum gpu memory consumption. - flush(); - - RefPtr image = adoptRef(m_canvas->newImageSnapshot()); - - // Early exit if canvas was not drawn to since last prepareMailbox - if (image->uniqueID() == m_lastImageId) - return false; - m_lastImageId = image->uniqueID(); - - MailboxInfo* mailboxInfo = createMailboxInfo(); - mailboxInfo->m_status = MailboxInUse; - mailboxInfo->m_image = image; - - ASSERT(mailboxInfo->m_mailbox.syncPoint == 0); - ASSERT(mailboxInfo->m_image.get()); - ASSERT(mailboxInfo->m_image->getTexture()); - - // Because of texture sharing with the compositor, we must invalidate - // the state cached in skia so that the deferred copy on write - // in SkSurface_Gpu does not make any false assumptions. - mailboxInfo->m_image->getTexture()->textureParamsModified(); - - webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->getTextureHandle()); - webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->m_mailbox.name); - if (isHidden()) { - // With hidden canvases, we release the SkImage immediately because - // there is no need for animations to be double buffered. - mailboxInfo->m_image.clear(); - } else { - webContext->flush(); - mailboxInfo->m_mailbox.syncPoint = webContext->insertSyncPoint(); - } - webContext->bindTexture(GL_TEXTURE_2D, 0); - // Because we are changing the texture binding without going through skia, - // we must dirty the context. - m_contextProvider->grContext()->resetContext(kTextureBinding_GrGLBackendState); - - // set m_parentLayerBridge to make sure 'this' stays alive as long as it has - // live mailboxes - ASSERT(!mailboxInfo->m_parentLayerBridge); - mailboxInfo->m_parentLayerBridge = this; - *outMailbox = mailboxInfo->m_mailbox; - - return true; -} - -Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::createMailboxInfo() { - ASSERT(!m_destructionInProgress); - MailboxInfo* mailboxInfo; - for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) { - if (mailboxInfo->m_status == MailboxAvailable) { - return mailboxInfo; - } - } - - // No available mailbox: create one. - m_mailboxes.grow(m_mailboxes.size() + 1); - mailboxInfo = &m_mailboxes.last(); - context()->genMailboxCHROMIUM(mailboxInfo->m_mailbox.name); - // Worst case, canvas is triple buffered. More than 3 active mailboxes - // means there is a problem. - // For the single-threaded case, this value needs to be at least - // kMaxSwapBuffersPending+1 (in render_widget.h). - // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2. - // TODO(piman): fix this. - ASSERT(m_mailboxes.size() <= 4); - ASSERT(mailboxInfo < m_mailboxes.end()); - return mailboxInfo; -} - -void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource) -{ - freeReleasedMailbox(); // Never have more than one mailbox in the released state. - bool contextLost = !m_isSurfaceValid || m_contextProvider->context3d()->isContextLost(); - Vector::iterator mailboxInfo; - for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) { - if (nameEquals(mailboxInfo->m_mailbox, mailbox)) { - mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; - ASSERT(mailboxInfo->m_status == MailboxInUse); - ASSERT(mailboxInfo->m_parentLayerBridge.get() == this); - - if (contextLost) { - // No need to clean up the mailbox resource, but make sure the - // mailbox can also be reusable once the context is restored. - mailboxInfo->m_status = MailboxAvailable; - m_releasedMailboxInfoIndex = InvalidMailboxIndex; - Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); - } else if (lostResource) { - // In case of the resource is lost, we need to delete the backing - // texture and remove the mailbox from list to avoid reusing it - // in future. - if (mailboxInfo->m_image) { - GrTexture* texture = mailboxInfo->m_image->getTexture(); - if (texture) - texture->textureParamsModified(); - mailboxInfo->m_image.clear(); - } - size_t i = mailboxInfo - m_mailboxes.begin(); - m_mailboxes.remove(i); - Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); - // Here we need to return early since mailboxInfo removal would - // also clear m_parentLayerBridge reference. - return; - } else { - mailboxInfo->m_status = MailboxReleased; - m_releasedMailboxInfoIndex = mailboxInfo - m_mailboxes.begin(); - m_framesSinceMailboxRelease = 0; - if (isHidden()) { - freeReleasedMailbox(); - } else { - ASSERT(!m_destructionInProgress); - Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); - } - } - // Trigger Canvas2DLayerBridge self-destruction if this is the - // last live mailbox and the layer bridge is not externally - // referenced. - mailboxInfo->m_parentLayerBridge.clear(); - return; - } - } -} - -WebLayer* Canvas2DLayerBridge::layer() const -{ - ASSERT(!m_destructionInProgress); - ASSERT(m_layer); - return m_layer->layer(); -} - -void Canvas2DLayerBridge::finalizeFrame() -{ - ASSERT(!m_destructionInProgress); - Canvas2DLayerManager::get().layerDidDraw(this); - m_didRecordDrawCommand = true; -} - -Platform3DObject Canvas2DLayerBridge::getBackingTexture() -{ - ASSERT(!m_destructionInProgress); - if (!checkSurfaceValid()) - return 0; - m_canvas->flush(); - context()->flush(); - GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget(); - if (renderTarget) { - return renderTarget->asTexture()->getTextureHandle(); - } - return 0; -} - -Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { - // This copy constructor should only be used for Vector reallocation - // Assuming 'other' is to be destroyed, we transfer m_image and - // m_parentLayerBridge ownership rather than do a refcount dance. - memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); - m_image = const_cast(&other)->m_image.release(); - m_parentLayerBridge = const_cast(&other)->m_parentLayerBridge.release(); - m_status = other.m_status; -} - -} // namespace blink diff --git a/engine/platform/graphics/Canvas2DLayerBridge.h b/engine/platform/graphics/Canvas2DLayerBridge.h deleted file mode 100644 index caa572082..000000000 --- a/engine/platform/graphics/Canvas2DLayerBridge.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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 SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DLAYERBRIDGE_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DLAYERBRIDGE_H_ - -#include "sky/engine/platform/PlatformExport.h" -#include "sky/engine/platform/geometry/IntSize.h" -#include "sky/engine/platform/graphics/ImageBufferSurface.h" -#include "sky/engine/public/platform/WebExternalTextureLayer.h" -#include "sky/engine/public/platform/WebExternalTextureLayerClient.h" -#include "sky/engine/public/platform/WebExternalTextureMailbox.h" -#include "sky/engine/wtf/DoublyLinkedList.h" -#include "sky/engine/wtf/PassOwnPtr.h" -#include "sky/engine/wtf/RefCounted.h" -#include "sky/engine/wtf/RefPtr.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/utils/SkDeferredCanvas.h" - -class Canvas2DLayerBridgeTest; - -namespace blink { - -class ImageBuffer; -class WebGraphicsContext3D; -class WebGraphicsContext3DProvider; - -class PLATFORM_EXPORT Canvas2DLayerBridge : public WebExternalTextureLayerClient, public SkDeferredCanvas::NotificationClient, public DoublyLinkedListNode, public RefCounted { - WTF_MAKE_NONCOPYABLE(Canvas2DLayerBridge); -public: - static PassRefPtr create(const IntSize&, OpacityMode, int msaaSampleCount); - - virtual ~Canvas2DLayerBridge(); - - // WebExternalTextureLayerClient implementation. - virtual bool prepareMailbox(WebExternalTextureMailbox*, WebExternalBitmap*) override; - virtual void mailboxReleased(const WebExternalTextureMailbox&, bool lostResource) override; - - // SkDeferredCanvas::NotificationClient implementation - virtual void prepareForDraw() override; - virtual void storageAllocatedForRecordingChanged(size_t) override; - virtual void flushedDrawCommands() override; - virtual void skippedPendingDrawCommands() override; - - // ImageBufferSurface implementation - void finalizeFrame(); - void willAccessPixels(); - SkCanvas* canvas() const { return m_canvas.get(); } - bool checkSurfaceValid(); - bool restoreSurface(); - WebLayer* layer() const; - Platform3DObject getBackingTexture(); - bool isAccelerated() const { return true; } - void setIsHidden(bool); - void setImageBuffer(ImageBuffer* imageBuffer) { m_imageBuffer = imageBuffer; } - - // Methods used by Canvas2DLayerManager - virtual size_t freeMemoryIfPossible(size_t); // virtual for mocking - virtual void flush(); // virtual for mocking - virtual size_t storageAllocatedForRecording(); // virtual for faking - size_t bytesAllocated() const { return m_bytesAllocated; } - void limitPendingFrames(); - void freeReleasedMailbox(); - bool hasReleasedMailbox() const; - void freeTransientResources(); - bool hasTransientResources() const; - bool isHidden() { return m_isHidden; } - - void beginDestruction(); - -protected: - Canvas2DLayerBridge(PassOwnPtr, PassOwnPtr, PassRefPtr, int, OpacityMode); - void setRateLimitingEnabled(bool); - bool releasedMailboxHasExpired(); - WebGraphicsContext3D* context(); - - OwnPtr m_canvas; - RefPtr m_surface; - OwnPtr m_layer; - OwnPtr m_contextProvider; - ImageBuffer* m_imageBuffer; - int m_msaaSampleCount; - size_t m_bytesAllocated; - bool m_didRecordDrawCommand; - bool m_isSurfaceValid; - int m_framesPending; - int m_framesSinceMailboxRelease; - bool m_destructionInProgress; - bool m_rateLimitingEnabled; - bool m_isHidden; - - friend class WTF::DoublyLinkedListNode; - friend class ::Canvas2DLayerBridgeTest; - Canvas2DLayerBridge* m_next; - Canvas2DLayerBridge* m_prev; - - enum MailboxStatus { - MailboxInUse, - MailboxReleased, - MailboxAvailable, - }; - - struct MailboxInfo { - WebExternalTextureMailbox m_mailbox; - RefPtr m_image; - MailboxStatus m_status; - RefPtr m_parentLayerBridge; - - MailboxInfo(const MailboxInfo&); - MailboxInfo() {} - }; - MailboxInfo* createMailboxInfo(); - MailboxInfo* releasedMailboxInfo(); - - uint32_t m_lastImageId; - Vector m_mailboxes; - int m_releasedMailboxInfoIndex; -}; - -} // namespace blink - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DLAYERBRIDGE_H_ diff --git a/engine/platform/graphics/Canvas2DLayerManager.cpp b/engine/platform/graphics/Canvas2DLayerManager.cpp deleted file mode 100644 index 001d54ed2..000000000 --- a/engine/platform/graphics/Canvas2DLayerManager.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* -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 INC. 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 INC. 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. -*/ - -#include "sky/engine/platform/graphics/Canvas2DLayerManager.h" - -#include "sky/engine/public/platform/Platform.h" -#include "sky/engine/wtf/StdLibExtras.h" - -namespace { - -enum { - DefaultMaxBytesAllocated = 64*1024*1024, - DefaultTargetBytesAllocated = 16*1024*1024, -}; - -} // unnamed namespace - -namespace blink { - -Canvas2DLayerManager::Canvas2DLayerManager() - : m_bytesAllocated(0) - , m_maxBytesAllocated(DefaultMaxBytesAllocated) - , m_targetBytesAllocated(DefaultTargetBytesAllocated) - , m_limitPendingFramesTimer(this, &Canvas2DLayerManager::limitPendingFramesTimerFired) -{ -} - -Canvas2DLayerManager::~Canvas2DLayerManager() -{ - ASSERT(!m_bytesAllocated); - ASSERT(!m_layerList.head()); -} - -void Canvas2DLayerManager::init(size_t maxBytesAllocated, size_t targetBytesAllocated) -{ - ASSERT(maxBytesAllocated >= targetBytesAllocated); - m_maxBytesAllocated = maxBytesAllocated; - m_targetBytesAllocated = targetBytesAllocated; - if (m_limitPendingFramesTimer.isActive()) - m_limitPendingFramesTimer.stop(); -} - -Canvas2DLayerManager& Canvas2DLayerManager::get() -{ - DEFINE_STATIC_LOCAL(Canvas2DLayerManager, manager, ()); - return manager; -} - -void Canvas2DLayerManager::limitPendingFramesTimerFired(Timer*) -{ - Canvas2DLayerBridge* layer = m_layerList.head(); - while (layer) { - Canvas2DLayerBridge* currentLayer = layer; - // must increment iterator before calling limitPendingFrames, which - // may result in the layer being removed from the list. - layer = layer->next(); - currentLayer->limitPendingFrames(); - } -} - -void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) -{ - if (isInList(layer)) { - if (layer != m_layerList.head()) { - m_layerList.remove(layer); - m_layerList.push(layer); // Set as MRU - } - } - - if (!m_limitPendingFramesTimer.isActive()) - m_limitPendingFramesTimer.startOneShot(0, FROM_HERE); -} - -void Canvas2DLayerManager::layerTransientResourceAllocationChanged(Canvas2DLayerBridge* layer, intptr_t deltaBytes) -{ - ASSERT((intptr_t)m_bytesAllocated + deltaBytes >= 0); - m_bytesAllocated = (intptr_t)m_bytesAllocated + deltaBytes; - if (!isInList(layer) && layer->hasTransientResources()) { - m_layerList.push(layer); - } else if (isInList(layer) && !layer->hasTransientResources()) { - m_layerList.remove(layer); - layer->setNext(0); - layer->setPrev(0); - } - - if (deltaBytes > 0) - freeMemoryIfNecessary(); -} - -void Canvas2DLayerManager::freeMemoryIfNecessary() -{ - if (m_bytesAllocated >= m_maxBytesAllocated) { - // Pass 1: Free memory from caches - Canvas2DLayerBridge* layer = m_layerList.tail(); // LRU - while (layer && m_bytesAllocated > m_targetBytesAllocated) { - Canvas2DLayerBridge* currentLayer = layer; - layer = layer->prev(); - currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated); - ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources()); - } - - // Pass 2: Flush canvases - layer = m_layerList.tail(); - while (m_bytesAllocated > m_targetBytesAllocated && layer) { - Canvas2DLayerBridge* currentLayer = layer; - layer = layer->prev(); - currentLayer->flush(); - currentLayer->freeMemoryIfPossible(m_bytesAllocated - m_targetBytesAllocated); - ASSERT(isInList(currentLayer) == currentLayer->hasTransientResources()); - } - } -} - -bool Canvas2DLayerManager::isInList(Canvas2DLayerBridge* layer) const -{ - return layer->prev() || m_layerList.head() == layer; -} - -} // namespace blink - diff --git a/engine/platform/graphics/Canvas2DLayerManager.h b/engine/platform/graphics/Canvas2DLayerManager.h deleted file mode 100644 index b282eb465..000000000 --- a/engine/platform/graphics/Canvas2DLayerManager.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -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 INC. 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 INC. 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 SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DLAYERMANAGER_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DLAYERMANAGER_H_ - -#include "sky/engine/platform/Timer.h" -#include "sky/engine/platform/graphics/Canvas2DLayerBridge.h" - -class Canvas2DLayerManagerTest; - -namespace blink { - -class PLATFORM_EXPORT Canvas2DLayerManager { -public: - static Canvas2DLayerManager& get(); - - void init(size_t maxBytesAllocated, size_t targetBytesAllocated); - virtual ~Canvas2DLayerManager(); - - void layerTransientResourceAllocationChanged(Canvas2DLayerBridge*, intptr_t deltaBytes = 0); - void layerDidDraw(Canvas2DLayerBridge*); - - bool isInList(Canvas2DLayerBridge*) const; -private: - Canvas2DLayerManager(); - - // internal methods - void freeMemoryIfNecessary(); - void addLayerToList(Canvas2DLayerBridge*); - - void limitPendingFramesTimerFired(Timer*); - - size_t m_bytesAllocated; - size_t m_maxBytesAllocated; - size_t m_targetBytesAllocated; - Timer m_limitPendingFramesTimer; - DoublyLinkedList m_layerList; - - friend class ::Canvas2DLayerManagerTest; // for unit testing -}; - -} // namespace blink - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_CANVAS2DLAYERMANAGER_H_ - diff --git a/engine/platform/graphics/GraphicsContext.cpp b/engine/platform/graphics/GraphicsContext.cpp index 5282fe1ed..225660ee9 100644 --- a/engine/platform/graphics/GraphicsContext.cpp +++ b/engine/platform/graphics/GraphicsContext.cpp @@ -72,15 +72,6 @@ public: virtual SkCanvas* canvas() const override { return m_surface ? m_surface->getCanvas() : 0; } virtual bool isValid() const override { return m_surface; } virtual bool isAccelerated() const override { return isValid() && m_surface->getCanvas()->getTopDevice()->accessRenderTarget(); } - virtual Platform3DObject getBackingTexture() const override - { - ASSERT(isAccelerated()); - GrRenderTarget* renderTarget = m_surface->getCanvas()->getTopDevice()->accessRenderTarget(); - if (renderTarget) { - return renderTarget->asTexture()->getTextureHandle(); - } - return 0; - }; private: RefPtr m_surface; diff --git a/engine/platform/graphics/GraphicsTypes3D.h b/engine/platform/graphics/GraphicsTypes3D.h deleted file mode 100644 index c0c4f460c..000000000 --- a/engine/platform/graphics/GraphicsTypes3D.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2011 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 COMPUTER, INC. ``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 COMPUTER, INC. OR - * 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 SKY_ENGINE_PLATFORM_GRAPHICS_GRAPHICSTYPES3D_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_GRAPHICSTYPES3D_H_ - -#include -#include "sky/engine/wtf/Forward.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" - -typedef unsigned Platform3DObject; - -// WebGL-specific enums -const unsigned GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL = 0x821A; -const unsigned GC3D_UNPACK_FLIP_Y_WEBGL = 0x9240; -const unsigned GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; -const unsigned GC3D_CONTEXT_LOST_WEBGL = 0x9242; -const unsigned GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; -const unsigned GC3D_BROWSER_DEFAULT_WEBGL = 0x9244; - -// GL_CHROMIUM_flipy -const unsigned GC3D_UNPACK_FLIP_Y_CHROMIUM = 0x9240; - -// GL_CHROMIUM_copy_texture -const unsigned GC3D_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM = 0x9241; -const unsigned GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM = 0x9242; - -// GL_AMD_compressed_ATC_texture -const unsigned GC3D_COMPRESSED_ATC_RGB_AMD = 0x8C92; -const unsigned GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD = 0x8C93; -const unsigned GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD = 0x87EE; - -// GL_CHROMIUM_image -const unsigned GC3D_IMAGE_ROWBYTES_CHROMIUM = 0x78F0; -const unsigned GC3D_IMAGE_MAP_CHROMIUM = 0x78F1; -const unsigned GC3D_IMAGE_SCANOUT_CHROMIUM = 0x78F2; - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_GRAPHICSTYPES3D_H_ diff --git a/engine/platform/graphics/ImageBuffer.cpp b/engine/platform/graphics/ImageBuffer.cpp index 7d4437f01..dbfa19b2a 100644 --- a/engine/platform/graphics/ImageBuffer.cpp +++ b/engine/platform/graphics/ImageBuffer.cpp @@ -38,11 +38,8 @@ #include "sky/engine/platform/geometry/IntRect.h" #include "sky/engine/platform/graphics/BitmapImage.h" #include "sky/engine/platform/graphics/GraphicsContext.h" -#include "sky/engine/platform/graphics/GraphicsTypes3D.h" #include "sky/engine/platform/graphics/ImageBufferClient.h" #include "sky/engine/platform/graphics/UnacceleratedImageBufferSurface.h" -#include "sky/engine/platform/graphics/gpu/DrawingBuffer.h" -#include "sky/engine/platform/graphics/gpu/Extensions3DUtil.h" #include "sky/engine/platform/graphics/skia/NativeImageSkia.h" #include "sky/engine/platform/graphics/skia/SkiaUtils.h" #include "sky/engine/public/platform/Platform.h" @@ -164,82 +161,12 @@ WebLayer* ImageBuffer::platformLayer() const return m_surface->layer(); } -bool ImageBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY) -{ - if (!m_surface->isAccelerated() || !platformLayer() || !isSurfaceValid()) - return false; - - if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, level)) - return false; - - OwnPtr provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); - if (!provider) - return false; - WebGraphicsContext3D* sharedContext = provider->context3d(); - if (!sharedContext) - return false; - - OwnPtr mailbox = adoptPtr(new WebExternalTextureMailbox); - - // Contexts may be in a different share group. We must transfer the texture through a mailbox first - sharedContext->genMailboxCHROMIUM(mailbox->name); - sharedContext->produceTextureDirectCHROMIUM(getBackingTexture(), GL_TEXTURE_2D, mailbox->name); - sharedContext->flush(); - - mailbox->syncPoint = sharedContext->insertSyncPoint(); - - context->waitSyncPoint(mailbox->syncPoint); - Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox->name); - - // The canvas is stored in a premultiplied format, so unpremultiply if necessary. - context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha); - - // The canvas is stored in an inverted position, so the flip semantics are reversed. - context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, !flipY); - context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType); - - context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, false); - context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false); - - context->deleteTexture(sourceTexture); - - context->flush(); - sharedContext->waitSyncPoint(context->insertSyncPoint()); - - // Undo grContext texture binding changes introduced in this function - provider->grContext()->resetContext(kTextureBinding_GrGLBackendState); - - return true; -} - static bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) { ASSERT(dst); return (src == dst); } -Platform3DObject ImageBuffer::getBackingTexture() -{ - return m_surface->getBackingTexture(); -} - -bool ImageBuffer::copyRenderingResultsFromDrawingBuffer(DrawingBuffer* drawingBuffer, bool fromFrontBuffer) -{ - if (!drawingBuffer) - return false; - OwnPtr provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); - if (!provider) - return false; - WebGraphicsContext3D* context3D = provider->context3d(); - Platform3DObject tex = m_surface->getBackingTexture(); - if (!context3D || !tex) - return false; - - m_surface->invalidateCachedBitmap(); - return drawingBuffer->copyToPlatformTexture(context3D, tex, GL_RGBA, - GL_UNSIGNED_BYTE, 0, true, false, fromFrontBuffer); -} - void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect* srcPtr, CompositeOperator op, WebBlendMode blendMode) { if (!isSurfaceValid()) diff --git a/engine/platform/graphics/ImageBuffer.h b/engine/platform/graphics/ImageBuffer.h index 53bed4703..fdb4ce385 100644 --- a/engine/platform/graphics/ImageBuffer.h +++ b/engine/platform/graphics/ImageBuffer.h @@ -31,10 +31,8 @@ #include "sky/engine/platform/PlatformExport.h" #include "sky/engine/platform/geometry/FloatRect.h" #include "sky/engine/platform/geometry/IntSize.h" -#include "sky/engine/platform/graphics/Canvas2DLayerBridge.h" #include "sky/engine/platform/graphics/ColorSpace.h" #include "sky/engine/platform/graphics/GraphicsTypes.h" -#include "sky/engine/platform/graphics/GraphicsTypes3D.h" #include "sky/engine/platform/graphics/ImageBufferSurface.h" #include "sky/engine/platform/transforms/AffineTransform.h" #include "sky/engine/wtf/Forward.h" @@ -45,7 +43,6 @@ namespace blink { -class DrawingBuffer; class GraphicsContext; class Image; class ImageBufferClient; @@ -109,16 +106,6 @@ public: void transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace); WebLayer* platformLayer() const; - // FIXME: current implementations of this method have the restriction that they only work - // with textures that are RGB or RGBA format, UNSIGNED_BYTE type and level 0, as specified in - // Extensions3D::canUseCopyTextureCHROMIUM(). - // Destroys the TEXTURE_2D binding for the active texture unit of the passed context - bool copyToPlatformTexture(WebGraphicsContext3D*, Platform3DObject, GLenum, GLenum, GLint, bool, bool); - - Platform3DObject getBackingTexture(); - - bool copyRenderingResultsFromDrawingBuffer(DrawingBuffer*, bool fromFrontBuffer = false); - void flush(); void notifySurfaceInvalid(); diff --git a/engine/platform/graphics/ImageBufferSurface.h b/engine/platform/graphics/ImageBufferSurface.h index a2e90f8f9..b52bf2653 100644 --- a/engine/platform/graphics/ImageBufferSurface.h +++ b/engine/platform/graphics/ImageBufferSurface.h @@ -33,7 +33,6 @@ #include "sky/engine/platform/PlatformExport.h" #include "sky/engine/platform/geometry/IntSize.h" -#include "sky/engine/platform/graphics/GraphicsTypes3D.h" #include "sky/engine/wtf/FastAllocBase.h" #include "sky/engine/wtf/Noncopyable.h" #include "sky/engine/wtf/PassRefPtr.h" @@ -65,7 +64,6 @@ public: virtual bool restore() { return false; }; virtual WebLayer* layer() const { return 0; }; virtual bool isAccelerated() const { return false; } - virtual Platform3DObject getBackingTexture() const { return 0; } virtual bool cachedBitmapEnabled() const { return false; } virtual const SkBitmap& cachedBitmap() const; virtual void invalidateCachedBitmap() { } diff --git a/engine/platform/graphics/gpu/DrawingBuffer.cpp b/engine/platform/graphics/gpu/DrawingBuffer.cpp deleted file mode 100644 index 7131cf095..000000000 --- a/engine/platform/graphics/gpu/DrawingBuffer.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -/* - * Copyright (c) 2010, 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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. - */ - - -#include "sky/engine/platform/graphics/gpu/DrawingBuffer.h" - -#include -#include "gen/sky/platform/RuntimeEnabledFeatures.h" -#include "sky/engine/platform/TraceEvent.h" -#include "sky/engine/platform/graphics/ImageBuffer.h" -#include "sky/engine/platform/graphics/gpu/Extensions3DUtil.h" -#include "sky/engine/public/platform/Platform.h" -#include "sky/engine/public/platform/WebExternalBitmap.h" -#include "sky/engine/public/platform/WebExternalTextureLayer.h" -#include "sky/engine/public/platform/WebGraphicsContext3D.h" -#include "sky/engine/public/platform/WebGraphicsContext3DProvider.h" -#ifndef NDEBUG -#include "sky/engine/wtf/RefCountedLeakCounter.h" -#endif - -namespace blink { - -namespace { -// Global resource ceiling (expressed in terms of pixels) for DrawingBuffer creation and resize. -// When this limit is set, DrawingBuffer::create() and DrawingBuffer::reset() calls that would -// exceed the global cap will instead clear the buffer. -const int s_maximumResourceUsePixels = 16 * 1024 * 1024; -int s_currentResourceUsePixels = 0; -const float s_resourceAdjustedRatio = 0.5; - -const bool s_allowContextEvictionOnCreate = true; -const int s_maxScaleAttempts = 3; - -DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, drawingBufferCounter, ("DrawingBuffer")); - -class ScopedTextureUnit0BindingRestorer { -public: - ScopedTextureUnit0BindingRestorer(WebGraphicsContext3D* context, GLenum activeTextureUnit, Platform3DObject textureUnitZeroId) - : m_context(context) - , m_oldActiveTextureUnit(activeTextureUnit) - , m_oldTextureUnitZeroId(textureUnitZeroId) - { - m_context->activeTexture(GL_TEXTURE0); - } - ~ScopedTextureUnit0BindingRestorer() - { - m_context->bindTexture(GL_TEXTURE_2D, m_oldTextureUnitZeroId); - m_context->activeTexture(m_oldActiveTextureUnit); - } - -private: - WebGraphicsContext3D* m_context; - GLenum m_oldActiveTextureUnit; - Platform3DObject m_oldTextureUnitZeroId; -}; - -} // namespace - -PassRefPtr DrawingBuffer::create(PassOwnPtr context, const IntSize& size, PreserveDrawingBuffer preserve, WebGraphicsContext3D::Attributes requestedAttributes, PassRefPtr contextEvictionManager) -{ - ASSERT(context); - OwnPtr extensionsUtil = Extensions3DUtil::create(context.get()); - if (!extensionsUtil) { - // This might be the first time we notice that the WebGraphicsContext3D is lost. - return nullptr; - } - bool multisampleSupported = extensionsUtil->supportsExtension("GL_CHROMIUM_framebuffer_multisample") - && extensionsUtil->supportsExtension("GL_OES_rgb8_rgba8"); - if (multisampleSupported) { - extensionsUtil->ensureExtensionEnabled("GL_CHROMIUM_framebuffer_multisample"); - extensionsUtil->ensureExtensionEnabled("GL_OES_rgb8_rgba8"); - } - bool packedDepthStencilSupported = extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil"); - if (packedDepthStencilSupported) - extensionsUtil->ensureExtensionEnabled("GL_OES_packed_depth_stencil"); - - RefPtr drawingBuffer = adoptRef(new DrawingBuffer(context, extensionsUtil.release(), multisampleSupported, packedDepthStencilSupported, preserve, requestedAttributes, contextEvictionManager)); - if (!drawingBuffer->initialize(size)) { - drawingBuffer->beginDestruction(); - return PassRefPtr(); - } - return drawingBuffer.release(); -} - -DrawingBuffer::DrawingBuffer(PassOwnPtr context, - PassOwnPtr extensionsUtil, - bool multisampleExtensionSupported, - bool packedDepthStencilExtensionSupported, - PreserveDrawingBuffer preserve, - WebGraphicsContext3D::Attributes requestedAttributes, - PassRefPtr contextEvictionManager) - : m_preserveDrawingBuffer(preserve) - , m_scissorEnabled(false) - , m_texture2DBinding(0) - , m_framebufferBinding(0) - , m_activeTextureUnit(GL_TEXTURE0) - , m_context(context) - , m_extensionsUtil(extensionsUtil) - , m_size(-1, -1) - , m_requestedAttributes(requestedAttributes) - , m_multisampleExtensionSupported(multisampleExtensionSupported) - , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported) - , m_fbo(0) - , m_depthStencilBuffer(0) - , m_depthBuffer(0) - , m_stencilBuffer(0) - , m_multisampleFBO(0) - , m_multisampleColorBuffer(0) - , m_contentsChanged(true) - , m_contentsChangeCommitted(false) - , m_layerComposited(false) - , m_multisampleMode(None) - , m_internalColorFormat(0) - , m_colorFormat(0) - , m_internalRenderbufferFormat(0) - , m_maxTextureSize(0) - , m_sampleCount(0) - , m_packAlignment(4) - , m_destructionInProgress(false) - , m_isHidden(false) - , m_contextEvictionManager(contextEvictionManager) -{ - // Used by browser tests to detect the use of a DrawingBuffer. - TRACE_EVENT_INSTANT0("test_gpu", "DrawingBufferCreation", TRACE_EVENT_SCOPE_NAME_PROCESS); -#ifndef NDEBUG - drawingBufferCounter.increment(); -#endif -} - -DrawingBuffer::~DrawingBuffer() -{ - ASSERT(m_destructionInProgress); - ASSERT(m_textureMailboxes.isEmpty()); - m_layer.clear(); - m_context.clear(); -#ifndef NDEBUG - drawingBufferCounter.decrement(); -#endif -} - -void DrawingBuffer::markContentsChanged() -{ - m_contentsChanged = true; - m_contentsChangeCommitted = false; - m_layerComposited = false; -} - -bool DrawingBuffer::layerComposited() const -{ - return m_layerComposited; -} - -void DrawingBuffer::markLayerComposited() -{ - m_layerComposited = true; -} - -WebGraphicsContext3D* DrawingBuffer::context() -{ - return m_context.get(); -} - -void DrawingBuffer::setIsHidden(bool hidden) -{ - if (m_isHidden == hidden) - return; - m_isHidden = hidden; - if (m_isHidden) - freeRecycledMailboxes(); -} - -void DrawingBuffer::freeRecycledMailboxes() -{ - if (m_recycledMailboxQueue.isEmpty()) - return; - while (!m_recycledMailboxQueue.isEmpty()) - deleteMailbox(m_recycledMailboxQueue.takeLast()); -} - -bool DrawingBuffer::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap) -{ - ASSERT(!m_isHidden); - if (!m_contentsChanged) - return false; - - if (m_destructionInProgress) { - // It can be hit in the following sequence. - // 1. WebGL draws something. - // 2. The compositor begins the frame. - // 3. Javascript makes a context lost using WEBGL_lose_context extension. - // 4. Here. - return false; - } - - // Resolve the multisampled buffer into m_colorBuffer texture. - if (m_multisampleMode != None) - commit(); - - if (bitmap) { - bitmap->setSize(size()); - - unsigned char* pixels = bitmap->pixels(); - bool needPremultiply = m_actualAttributes.alpha && !m_actualAttributes.premultipliedAlpha; - WebGLImageConversion::AlphaOp op = needPremultiply ? WebGLImageConversion::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing; - if (pixels) - readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSkia, op); - } - - // We must restore the texture binding since creating new textures, - // consuming and producing mailboxes changes it. - ScopedTextureUnit0BindingRestorer restorer(m_context.get(), m_activeTextureUnit, m_texture2DBinding); - - // First try to recycle an old buffer. - RefPtr frontColorBufferMailbox = recycledMailbox(); - - // No buffer available to recycle, create a new one. - if (!frontColorBufferMailbox) { - TextureInfo newTexture; - newTexture.textureId = createColorTexture(); - allocateTextureMemory(&newTexture, m_size); - // Bad things happened, abandon ship. - if (!newTexture.textureId) - return false; - - frontColorBufferMailbox = createNewMailbox(newTexture); - } - - if (m_preserveDrawingBuffer == Discard) { - std::swap(frontColorBufferMailbox->textureInfo, m_colorBuffer); - // It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a - // WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding. - // If this stops being true at some point, we should track the current framebuffer binding in the DrawingBuffer and restore - // it after attaching the new back buffer here. - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); - if (m_multisampleMode == ImplicitResolve) - m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount); - else - m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0); - } else { - m_context->copyTextureCHROMIUM(GL_TEXTURE_2D, m_colorBuffer.textureId, frontColorBufferMailbox->textureInfo.textureId, 0, GL_RGBA, GL_UNSIGNED_BYTE); - } - - if (m_multisampleMode != None && !m_framebufferBinding) - bind(); - else - restoreFramebufferBinding(); - - m_contentsChanged = false; - - m_context->produceTextureDirectCHROMIUM(frontColorBufferMailbox->textureInfo.textureId, GL_TEXTURE_2D, frontColorBufferMailbox->mailbox.name); - m_context->flush(); - frontColorBufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint(); - frontColorBufferMailbox->mailbox.allowOverlay = frontColorBufferMailbox->textureInfo.imageId != 0; - markLayerComposited(); - - // set m_parentDrawingBuffer to make sure 'this' stays alive as long as it has live mailboxes - ASSERT(!frontColorBufferMailbox->m_parentDrawingBuffer); - frontColorBufferMailbox->m_parentDrawingBuffer = this; - *outMailbox = frontColorBufferMailbox->mailbox; - m_frontColorBuffer = frontColorBufferMailbox->textureInfo; - return true; -} - -void DrawingBuffer::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource) -{ - if (m_destructionInProgress || m_context->isContextLost() || lostResource || m_isHidden) { - mailboxReleasedWithoutRecycling(mailbox); - return; - } - - for (size_t i = 0; i < m_textureMailboxes.size(); i++) { - RefPtr mailboxInfo = m_textureMailboxes[i]; - if (nameEquals(mailboxInfo->mailbox, mailbox)) { - mailboxInfo->mailbox.syncPoint = mailbox.syncPoint; - ASSERT(mailboxInfo->m_parentDrawingBuffer.get() == this); - mailboxInfo->m_parentDrawingBuffer.clear(); - m_recycledMailboxQueue.prepend(mailboxInfo->mailbox); - return; - } - } - ASSERT_NOT_REACHED(); -} - -void DrawingBuffer::mailboxReleasedWithoutRecycling(const WebExternalTextureMailbox& mailbox) -{ - ASSERT(m_textureMailboxes.size()); - // Ensure not to call the destructor until deleteMailbox() is completed. - RefPtr self = this; - deleteMailbox(mailbox); -} - -PassRefPtr DrawingBuffer::recycledMailbox() -{ - if (m_recycledMailboxQueue.isEmpty()) - return PassRefPtr(); - - WebExternalTextureMailbox mailbox; - while (!m_recycledMailboxQueue.isEmpty()) { - mailbox = m_recycledMailboxQueue.takeLast(); - // Never have more than one mailbox in the released state. - if (!m_recycledMailboxQueue.isEmpty()) - deleteMailbox(mailbox); - } - - RefPtr mailboxInfo; - for (size_t i = 0; i < m_textureMailboxes.size(); i++) { - if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) { - mailboxInfo = m_textureMailboxes[i]; - break; - } - } - ASSERT(mailboxInfo); - - if (mailboxInfo->mailbox.syncPoint) { - m_context->waitSyncPoint(mailboxInfo->mailbox.syncPoint); - mailboxInfo->mailbox.syncPoint = 0; - } - - if (mailboxInfo->size != m_size) { - m_context->bindTexture(GL_TEXTURE_2D, mailboxInfo->textureInfo.textureId); - allocateTextureMemory(&mailboxInfo->textureInfo, m_size); - mailboxInfo->size = m_size; - } - - return mailboxInfo.release(); -} - -PassRefPtr DrawingBuffer::createNewMailbox(const TextureInfo& info) -{ - RefPtr returnMailbox = adoptRef(new MailboxInfo()); - m_context->genMailboxCHROMIUM(returnMailbox->mailbox.name); - returnMailbox->textureInfo = info; - returnMailbox->size = m_size; - m_textureMailboxes.append(returnMailbox); - return returnMailbox.release(); -} - -void DrawingBuffer::deleteMailbox(const WebExternalTextureMailbox& mailbox) -{ - for (size_t i = 0; i < m_textureMailboxes.size(); i++) { - if (nameEquals(m_textureMailboxes[i]->mailbox, mailbox)) { - if (mailbox.syncPoint) - m_context->waitSyncPoint(mailbox.syncPoint); - - deleteChromiumImageForTexture(&m_textureMailboxes[i]->textureInfo); - - m_context->deleteTexture(m_textureMailboxes[i]->textureInfo.textureId); - m_textureMailboxes.remove(i); - return; - } - } - ASSERT_NOT_REACHED(); -} - -bool DrawingBuffer::initialize(const IntSize& size) -{ - if (m_context->isContextLost()) { - // Need to try to restore the context again later. - return false; - } - - if (m_requestedAttributes.alpha) { - m_internalColorFormat = GL_RGBA; - m_colorFormat = GL_RGBA; - m_internalRenderbufferFormat = GL_RGBA8_OES; - } else { - m_internalColorFormat = GL_RGB; - m_colorFormat = GL_RGB; - m_internalRenderbufferFormat = GL_RGB8_OES; - } - - m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); - - int maxSampleCount = 0; - m_multisampleMode = None; - if (m_requestedAttributes.antialias && m_multisampleExtensionSupported) { - m_context->getIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSampleCount); - m_multisampleMode = ExplicitResolve; - if (m_extensionsUtil->supportsExtension("GL_EXT_multisampled_render_to_texture")) - m_multisampleMode = ImplicitResolve; - } - m_sampleCount = std::min(4, maxSampleCount); - - m_fbo = m_context->createFramebuffer(); - - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); - m_colorBuffer.textureId = createColorTexture(); - if (m_multisampleMode == ImplicitResolve) - m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount); - else - m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0); - createSecondaryBuffers(); - // We first try to initialize everything with the requested attributes. - if (!reset(size)) - return false; - // If that succeeds, we then see what we actually got and update our actual attributes to reflect that. - m_actualAttributes = m_requestedAttributes; - if (m_requestedAttributes.alpha) { - WGC3Dint alphaBits = 0; - m_context->getIntegerv(GL_ALPHA_BITS, &alphaBits); - m_actualAttributes.alpha = alphaBits > 0; - } - if (m_requestedAttributes.depth) { - WGC3Dint depthBits = 0; - m_context->getIntegerv(GL_DEPTH_BITS, &depthBits); - m_actualAttributes.depth = depthBits > 0; - } - if (m_requestedAttributes.stencil) { - WGC3Dint stencilBits = 0; - m_context->getIntegerv(GL_STENCIL_BITS, &stencilBits); - m_actualAttributes.stencil = stencilBits > 0; - } - m_actualAttributes.antialias = multisample(); - return true; -} - -bool DrawingBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, bool fromFrontBuffer) -{ - GLint textureId = m_colorBuffer.textureId; - if (fromFrontBuffer && m_frontColorBuffer.textureId) - textureId = m_frontColorBuffer.textureId; - - if (m_contentsChanged) { - if (m_multisampleMode != None) { - commit(); - if (!m_framebufferBinding) - bind(); - else - restoreFramebufferBinding(); - } - m_context->flush(); - } - - if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, level)) - return false; - - // Contexts may be in a different share group. We must transfer the texture through a mailbox first - RefPtr bufferMailbox = adoptRef(new MailboxInfo()); - m_context->genMailboxCHROMIUM(bufferMailbox->mailbox.name); - m_context->produceTextureDirectCHROMIUM(textureId, GL_TEXTURE_2D, bufferMailbox->mailbox.name); - m_context->flush(); - - bufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint(); - - context->waitSyncPoint(bufferMailbox->mailbox.syncPoint); - Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, bufferMailbox->mailbox.name); - - bool unpackPremultiplyAlphaNeeded = false; - bool unpackUnpremultiplyAlphaNeeded = false; - if (m_actualAttributes.alpha && m_actualAttributes.premultipliedAlpha && !premultiplyAlpha) - unpackUnpremultiplyAlphaNeeded = true; - else if (m_actualAttributes.alpha && !m_actualAttributes.premultipliedAlpha && premultiplyAlpha) - unpackPremultiplyAlphaNeeded = true; - - context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, unpackUnpremultiplyAlphaNeeded); - context->pixelStorei(GC3D_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, unpackPremultiplyAlphaNeeded); - context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, flipY); - context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType); - context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, false); - context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false); - context->pixelStorei(GC3D_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, false); - - context->deleteTexture(sourceTexture); - - context->flush(); - m_context->waitSyncPoint(context->insertSyncPoint()); - - return true; -} - -Platform3DObject DrawingBuffer::framebuffer() const -{ - return m_fbo; -} - -WebLayer* DrawingBuffer::platformLayer() -{ - if (!m_layer) { - m_layer = nullptr; - CRASH(); // No compositor. - - m_layer->setOpaque(!m_actualAttributes.alpha); - m_layer->setBlendBackgroundColor(m_actualAttributes.alpha); - m_layer->setPremultipliedAlpha(m_actualAttributes.premultipliedAlpha); - } - - return m_layer->layer(); -} - -void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer) -{ - if (m_context->getGraphicsResetStatusARB() != GL_NO_ERROR) - return; - - if (!imageBuffer) - return; - Platform3DObject tex = imageBuffer->getBackingTexture(); - if (tex) { - RefPtr bufferMailbox = adoptRef(new MailboxInfo()); - m_context->genMailboxCHROMIUM(bufferMailbox->mailbox.name); - m_context->produceTextureDirectCHROMIUM(m_frontColorBuffer.textureId, GL_TEXTURE_2D, bufferMailbox->mailbox.name); - m_context->flush(); - - bufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint(); - OwnPtr provider = - adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); - if (!provider) - return; - WebGraphicsContext3D* context = provider->context3d(); - if (!context) - return; - - context->waitSyncPoint(bufferMailbox->mailbox.syncPoint); - Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, bufferMailbox->mailbox.name); - context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, - tex, 0, GL_RGBA, GL_UNSIGNED_BYTE); - context->deleteTexture(sourceTexture); - context->flush(); - m_context->waitSyncPoint(context->insertSyncPoint()); - return; - } - - Platform3DObject framebuffer = m_context->createFramebuffer(); - m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); - // We don't need to bind a copy of m_frontColorBuffer since the texture parameters are untouched. - m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_frontColorBuffer.textureId, 0); - - paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_actualAttributes.premultipliedAlpha, imageBuffer); - m_context->deleteFramebuffer(framebuffer); - // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding). - restoreFramebufferBinding(); -} - -void DrawingBuffer::clearPlatformLayer() -{ - if (m_layer) - m_layer->clearTexture(); - - m_context->flush(); -} - -void DrawingBuffer::beginDestruction() -{ - ASSERT(!m_destructionInProgress); - m_destructionInProgress = true; - - clearPlatformLayer(); - - while (!m_recycledMailboxQueue.isEmpty()) - deleteMailbox(m_recycledMailboxQueue.takeLast()); - - if (m_multisampleFBO) - m_context->deleteFramebuffer(m_multisampleFBO); - - if (m_fbo) - m_context->deleteFramebuffer(m_fbo); - - if (m_multisampleColorBuffer) - m_context->deleteRenderbuffer(m_multisampleColorBuffer); - - if (m_depthStencilBuffer) - m_context->deleteRenderbuffer(m_depthStencilBuffer); - - if (m_depthBuffer) - m_context->deleteRenderbuffer(m_depthBuffer); - - if (m_stencilBuffer) - m_context->deleteRenderbuffer(m_stencilBuffer); - - if (m_colorBuffer.textureId) { - deleteChromiumImageForTexture(&m_colorBuffer); - m_context->deleteTexture(m_colorBuffer.textureId); - } - - setSize(IntSize()); - - m_colorBuffer = TextureInfo(); - m_frontColorBuffer = TextureInfo(); - m_multisampleColorBuffer = 0; - m_depthStencilBuffer = 0; - m_depthBuffer = 0; - m_stencilBuffer = 0; - m_multisampleFBO = 0; - m_fbo = 0; - m_contextEvictionManager.clear(); -} - -unsigned DrawingBuffer::createColorTexture() -{ - unsigned offscreenColorTexture = m_context->createTexture(); - if (!offscreenColorTexture) - return 0; - - m_context->bindTexture(GL_TEXTURE_2D, offscreenColorTexture); - m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - return offscreenColorTexture; -} - -void DrawingBuffer::createSecondaryBuffers() -{ - // create a multisample FBO - if (m_multisampleMode == ExplicitResolve) { - m_multisampleFBO = m_context->createFramebuffer(); - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); - m_multisampleColorBuffer = m_context->createRenderbuffer(); - } -} - -bool DrawingBuffer::resizeFramebuffer(const IntSize& size) -{ - // resize regular FBO - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); - - m_context->bindTexture(GL_TEXTURE_2D, m_colorBuffer.textureId); - - allocateTextureMemory(&m_colorBuffer, size); - - if (m_multisampleMode == ImplicitResolve) - m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0, m_sampleCount); - else - m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer.textureId, 0); - - m_context->bindTexture(GL_TEXTURE_2D, 0); - - if (m_multisampleMode != ExplicitResolve) - resizeDepthStencil(size); - if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - return false; - - return true; -} - -bool DrawingBuffer::resizeMultisampleFramebuffer(const IntSize& size) -{ - if (m_multisampleMode == ExplicitResolve) { - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); - - m_context->bindRenderbuffer(GL_RENDERBUFFER, m_multisampleColorBuffer); - m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, m_internalRenderbufferFormat, size.width(), size.height()); - - if (m_context->getError() == GL_OUT_OF_MEMORY) - return false; - - m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_multisampleColorBuffer); - resizeDepthStencil(size); - if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - return false; - } - - return true; -} - -void DrawingBuffer::resizeDepthStencil(const IntSize& size) -{ - if (!m_requestedAttributes.depth && !m_requestedAttributes.stencil) - return; - - if (m_packedDepthStencilExtensionSupported) { - if (!m_depthStencilBuffer) - m_depthStencilBuffer = m_context->createRenderbuffer(); - m_context->bindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); - if (m_multisampleMode == ImplicitResolve) - m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height()); - else if (m_multisampleMode == ExplicitResolve) - m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH24_STENCIL8_OES, size.width(), size.height()); - else - m_context->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, size.width(), size.height()); - m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); - m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); - } else { - if (m_requestedAttributes.depth) { - if (!m_depthBuffer) - m_depthBuffer = m_context->createRenderbuffer(); - m_context->bindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); - if (m_multisampleMode == ImplicitResolve) - m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH_COMPONENT16, size.width(), size.height()); - else if (m_multisampleMode == ExplicitResolve) - m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, GL_DEPTH_COMPONENT16, size.width(), size.height()); - else - m_context->renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.width(), size.height()); - m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); - } - if (m_requestedAttributes.stencil) { - if (!m_stencilBuffer) - m_stencilBuffer = m_context->createRenderbuffer(); - m_context->bindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); - if (m_multisampleMode == ImplicitResolve) - m_context->renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, m_sampleCount, GL_STENCIL_INDEX8, size.width(), size.height()); - else if (m_multisampleMode == ExplicitResolve) - m_context->renderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, m_sampleCount, GL_STENCIL_INDEX8, size.width(), size.height()); - else - m_context->renderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, size.width(), size.height()); - m_context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); - } - } - m_context->bindRenderbuffer(GL_RENDERBUFFER, 0); -} - - - -void DrawingBuffer::clearFramebuffers(GLbitfield clearMask) -{ - // We will clear the multisample FBO, but we also need to clear the non-multisampled buffer. - if (m_multisampleFBO) { - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); - m_context->clear(GL_COLOR_BUFFER_BIT); - } - - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo); - m_context->clear(clearMask); -} - -void DrawingBuffer::setSize(const IntSize& size) -{ - if (m_size == size) - return; - - s_currentResourceUsePixels += pixelDelta(size, m_size); - m_size = size; -} - -int DrawingBuffer::pixelDelta(const IntSize& newSize, const IntSize& curSize) -{ - return (std::max(0, newSize.width()) * std::max(0, newSize.height())) - (std::max(0, curSize.width()) * std::max(0, curSize.height())); -} - -IntSize DrawingBuffer::adjustSize(const IntSize& desiredSize, const IntSize& curSize, int maxTextureSize) -{ - IntSize adjustedSize = desiredSize; - - // Clamp if the desired size is greater than the maximum texture size for the device. - if (adjustedSize.height() > maxTextureSize) - adjustedSize.setHeight(maxTextureSize); - - if (adjustedSize.width() > maxTextureSize) - adjustedSize.setWidth(maxTextureSize); - - // Try progressively smaller sizes until we find a size that fits or reach a scale limit. - int scaleAttempts = 0; - while ((s_currentResourceUsePixels + pixelDelta(adjustedSize, curSize)) > s_maximumResourceUsePixels) { - scaleAttempts++; - if (scaleAttempts > s_maxScaleAttempts) - return IntSize(); - - adjustedSize.scale(s_resourceAdjustedRatio); - - if (adjustedSize.isEmpty()) - return IntSize(); - } - - return adjustedSize; -} - -IntSize DrawingBuffer::adjustSizeWithContextEviction(const IntSize& size, bool& evictContext) -{ - IntSize adjustedSize = adjustSize(size, m_size, m_maxTextureSize); - if (!adjustedSize.isEmpty()) { - evictContext = false; - return adjustedSize; // Buffer fits without evicting a context. - } - - // Speculatively adjust the pixel budget to see if the buffer would fit should the oldest context be evicted. - IntSize oldestSize = m_contextEvictionManager->oldestContextSize(); - int pixelDelta = oldestSize.width() * oldestSize.height(); - - s_currentResourceUsePixels -= pixelDelta; - adjustedSize = adjustSize(size, m_size, m_maxTextureSize); - s_currentResourceUsePixels += pixelDelta; - - evictContext = !adjustedSize.isEmpty(); - return adjustedSize; -} - -bool DrawingBuffer::reset(const IntSize& newSize) -{ - ASSERT(!newSize.isEmpty()); - IntSize adjustedSize; - bool evictContext = false; - bool isNewContext = m_size.isEmpty(); - if (s_allowContextEvictionOnCreate && isNewContext) - adjustedSize = adjustSizeWithContextEviction(newSize, evictContext); - else - adjustedSize = adjustSize(newSize, m_size, m_maxTextureSize); - - if (adjustedSize.isEmpty()) - return false; - - if (evictContext) - m_contextEvictionManager->forciblyLoseOldestContext("WARNING: WebGL contexts have exceeded the maximum allowed backbuffer area. Oldest context will be lost."); - - if (adjustedSize != m_size) { - do { - // resize multisample FBO - if (!resizeMultisampleFramebuffer(adjustedSize) || !resizeFramebuffer(adjustedSize)) { - adjustedSize.scale(s_resourceAdjustedRatio); - continue; - } - break; - } while (!adjustedSize.isEmpty()); - - setSize(adjustedSize); - - if (adjustedSize.isEmpty()) - return false; - } - - m_context->disable(GL_SCISSOR_TEST); - m_context->clearColor(0, 0, 0, 0); - m_context->colorMask(true, true, true, true); - - GLbitfield clearMask = GL_COLOR_BUFFER_BIT; - if (m_actualAttributes.depth) { - m_context->clearDepth(1.0f); - clearMask |= GL_DEPTH_BUFFER_BIT; - m_context->depthMask(true); - } - if (m_actualAttributes.stencil) { - m_context->clearStencil(0); - clearMask |= GL_STENCIL_BUFFER_BIT; - m_context->stencilMaskSeparate(GL_FRONT, 0xFFFFFFFF); - } - - clearFramebuffers(clearMask); - return true; -} - -void DrawingBuffer::commit(long x, long y, long width, long height) -{ - if (width < 0) - width = m_size.width(); - if (height < 0) - height = m_size.height(); - - if (m_multisampleFBO && !m_contentsChangeCommitted) { - m_context->bindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO); - m_context->bindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo); - - if (m_scissorEnabled) - m_context->disable(GL_SCISSOR_TEST); - - // Use NEAREST, because there is no scale performed during the blit. - m_context->blitFramebufferCHROMIUM(x, y, width, height, x, y, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - if (m_scissorEnabled) - m_context->enable(GL_SCISSOR_TEST); - } - - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); - m_contentsChangeCommitted = true; -} - -void DrawingBuffer::restoreFramebufferBinding() -{ - if (!m_framebufferBinding) - return; - - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_framebufferBinding); -} - -bool DrawingBuffer::multisample() const -{ - return m_multisampleMode != None; -} - -void DrawingBuffer::bind() -{ - m_context->bindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO ? m_multisampleFBO : m_fbo); -} - -void DrawingBuffer::setPackAlignment(GLint param) -{ - m_packAlignment = param; -} - -void DrawingBuffer::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer) -{ - paintFramebufferToCanvas(framebuffer(), size().width(), size().height(), !m_actualAttributes.premultipliedAlpha, imageBuffer); -} - -PassRefPtr DrawingBuffer::paintRenderingResultsToImageData(int& width, int& height) -{ - if (m_actualAttributes.premultipliedAlpha) - return nullptr; - - width = size().width(); - height = size().height(); - - Checked dataSize = 4; - dataSize *= width; - dataSize *= height; - if (dataSize.hasOverflowed()) - return nullptr; - - RefPtr pixels = Uint8ClampedArray::createUninitialized(width * height * 4); - - m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer()); - readBackFramebuffer(pixels->data(), width, height, ReadbackRGBA, WebGLImageConversion::AlphaDoNothing); - flipVertically(pixels->data(), width, height); - - return pixels.release(); -} - -void DrawingBuffer::paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer* imageBuffer) -{ - unsigned char* pixels = 0; - - const SkBitmap& canvasBitmap = imageBuffer->bitmap(); - const SkBitmap* readbackBitmap = 0; - ASSERT(canvasBitmap.colorType() == kN32_SkColorType); - if (canvasBitmap.width() == width && canvasBitmap.height() == height) { - // This is the fastest and most common case. We read back - // directly into the canvas's backing store. - readbackBitmap = &canvasBitmap; - m_resizingBitmap.reset(); - } else { - // We need to allocate a temporary bitmap for reading back the - // pixel data. We will then use Skia to rescale this bitmap to - // the size of the canvas's backing store. - if (m_resizingBitmap.width() != width || m_resizingBitmap.height() != height) - m_resizingBitmap.allocN32Pixels(width, height); - readbackBitmap = &m_resizingBitmap; - } - - // Read back the frame buffer. - SkAutoLockPixels bitmapLock(*readbackBitmap); - pixels = static_cast(readbackBitmap->getPixels()); - - m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); - readBackFramebuffer(pixels, width, height, ReadbackSkia, premultiplyAlpha ? WebGLImageConversion::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing); - flipVertically(pixels, width, height); - - readbackBitmap->notifyPixelsChanged(); - if (m_resizingBitmap.readyToDraw()) { - // We need to draw the resizing bitmap into the canvas's backing store. - SkCanvas canvas(canvasBitmap); - SkRect dst; - dst.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(canvasBitmap.width()), SkIntToScalar(canvasBitmap.height())); - canvas.drawBitmapRect(m_resizingBitmap, 0, dst); - } -} - -void DrawingBuffer::readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder readbackOrder, WebGLImageConversion::AlphaOp op) -{ - if (m_packAlignment > 4) - m_context->pixelStorei(GL_PACK_ALIGNMENT, 1); - m_context->readPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - if (m_packAlignment > 4) - m_context->pixelStorei(GL_PACK_ALIGNMENT, m_packAlignment); - - size_t bufferSize = 4 * width * height; - - if (readbackOrder == ReadbackSkia) { -#if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT - // Swizzle red and blue channels to match SkBitmap's byte ordering. - // TODO(kbr): expose GL_BGRA as extension. - for (size_t i = 0; i < bufferSize; i += 4) { - std::swap(pixels[i], pixels[i + 2]); - } -#endif - } - - if (op == WebGLImageConversion::AlphaDoPremultiply) { - for (size_t i = 0; i < bufferSize; i += 4) { - pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); - pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); - pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); - } - } else if (op != WebGLImageConversion::AlphaDoNothing) { - ASSERT_NOT_REACHED(); - } -} - -void DrawingBuffer::flipVertically(uint8_t* framebuffer, int width, int height) -{ - m_scanline.resize(width * 4); - uint8* scanline = &m_scanline[0]; - unsigned rowBytes = width * 4; - unsigned count = height / 2; - for (unsigned i = 0; i < count; i++) { - uint8* rowA = framebuffer + i * rowBytes; - uint8* rowB = framebuffer + (height - i - 1) * rowBytes; - memcpy(scanline, rowB, rowBytes); - memcpy(rowB, rowA, rowBytes); - memcpy(rowA, scanline, rowBytes); - } -} - -void DrawingBuffer::texImage2DResourceSafe(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint unpackAlignment) -{ - ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8); - m_context->texImage2D(target, level, internalformat, width, height, border, format, type, 0); -} - -void DrawingBuffer::allocateTextureMemory(TextureInfo* info, const IntSize& size) -{ - if (RuntimeEnabledFeatures::webGLImageChromiumEnabled()) { - deleteChromiumImageForTexture(info); - - info->imageId = m_context->createImageCHROMIUM(size.width(), size.height(), GL_RGBA8_OES, GC3D_IMAGE_SCANOUT_CHROMIUM); - if (info->imageId) { - m_context->bindTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId); - return; - } - } - - texImage2DResourceSafe(GL_TEXTURE_2D, 0, m_internalColorFormat, size.width(), size.height(), 0, m_colorFormat, GL_UNSIGNED_BYTE); -} - -void DrawingBuffer::deleteChromiumImageForTexture(TextureInfo* info) -{ - if (info->imageId) { - m_context->releaseTexImage2DCHROMIUM(GL_TEXTURE_2D, info->imageId); - m_context->destroyImageCHROMIUM(info->imageId); - info->imageId = 0; - } -} - -} // namespace blink diff --git a/engine/platform/graphics/gpu/DrawingBuffer.h b/engine/platform/graphics/gpu/DrawingBuffer.h deleted file mode 100644 index 093a6c275..000000000 --- a/engine/platform/graphics/gpu/DrawingBuffer.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2010, 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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 SKY_ENGINE_PLATFORM_GRAPHICS_GPU_DRAWINGBUFFER_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_GPU_DRAWINGBUFFER_H_ - -#include "sky/engine/platform/PlatformExport.h" -#include "sky/engine/platform/geometry/IntSize.h" -#include "sky/engine/platform/graphics/GraphicsTypes3D.h" -#include "sky/engine/platform/graphics/gpu/WebGLImageConversion.h" -#include "sky/engine/public/platform/WebExternalTextureLayerClient.h" -#include "sky/engine/public/platform/WebExternalTextureMailbox.h" -#include "sky/engine/public/platform/WebGraphicsContext3D.h" -#include "sky/engine/wtf/Deque.h" -#include "sky/engine/wtf/Noncopyable.h" -#include "sky/engine/wtf/OwnPtr.h" -#include "sky/engine/wtf/PassOwnPtr.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" -#include "third_party/skia/include/core/SkBitmap.h" - -namespace blink { - -class Extensions3DUtil; -class ImageBuffer; -class WebExternalBitmap; -class WebExternalTextureLayer; -class WebGraphicsContext3D; -class WebLayer; - -// Abstract interface to allow basic context eviction management -class PLATFORM_EXPORT ContextEvictionManager : public RefCounted { -public: - virtual ~ContextEvictionManager() {}; - - virtual void forciblyLoseOldestContext(const String& reason) = 0; - virtual IntSize oldestContextSize() = 0; -}; - -// Manages a rendering target (framebuffer + attachment) for a canvas. Can publish its rendering -// results to a WebLayer for compositing. -class PLATFORM_EXPORT DrawingBuffer : public RefCounted, public WebExternalTextureLayerClient { - // If we used CHROMIUM_image as the backing storage for our buffers, - // we need to know the mapping from texture id to image. - struct TextureInfo { - Platform3DObject textureId; - WGC3Duint imageId; - - TextureInfo() - : textureId(0) - , imageId(0) - { - } - }; - - struct MailboxInfo : public RefCounted { - WebExternalTextureMailbox mailbox; - TextureInfo textureInfo; - IntSize size; - // This keeps the parent drawing buffer alive as long as the compositor is - // referring to one of the mailboxes DrawingBuffer produced. The parent drawing buffer is - // cleared when the compositor returns the mailbox. See mailboxReleased(). - RefPtr m_parentDrawingBuffer; - }; -public: - enum PreserveDrawingBuffer { - Preserve, - Discard - }; - - static PassRefPtr create(PassOwnPtr, const IntSize&, PreserveDrawingBuffer, WebGraphicsContext3D::Attributes requestedAttributes, PassRefPtr); - - virtual ~DrawingBuffer(); - - // Destruction will be completed after all mailboxes are released. - void beginDestruction(); - - // Issues a glClear() on all framebuffers associated with this DrawingBuffer. The caller is responsible for - // making the context current and setting the clear values and masks. Modifies the framebuffer binding. - void clearFramebuffers(GLbitfield clearMask); - - // Given the desired buffer size, provides the largest dimensions that will fit in the pixel budget. - static IntSize adjustSize(const IntSize& desiredSize, const IntSize& curSize, int maxTextureSize); - bool reset(const IntSize&); - void bind(); - IntSize size() const { return m_size; } - - // Copies the multisample color buffer to the normal color buffer and leaves m_fbo bound. - void commit(long x = 0, long y = 0, long width = -1, long height = -1); - - // commit should copy the full multisample buffer, and not respect the - // current scissor bounds. Track the state of the scissor test so that it - // can be disabled during calls to commit. - void setScissorEnabled(bool scissorEnabled) { m_scissorEnabled = scissorEnabled; } - - // The DrawingBuffer needs to track the texture bound to texture unit 0. - // The bound texture is tracked to avoid costly queries during rendering. - void setTexture2DBinding(Platform3DObject texture) { m_texture2DBinding = texture; } - - // The DrawingBuffer needs to track the currently bound framebuffer so it - // restore the binding when needed. - void setFramebufferBinding(Platform3DObject fbo) { m_framebufferBinding = fbo; } - - // Track the currently active texture unit. Texture unit 0 is used as host for a scratch - // texture. - void setActiveTextureUnit(GLint textureUnit) { m_activeTextureUnit = textureUnit; } - - bool multisample() const; - - Platform3DObject framebuffer() const; - - void markContentsChanged(); - void markLayerComposited(); - bool layerComposited() const; - void setIsHidden(bool); - - WebLayer* platformLayer(); - void paintCompositedResultsToCanvas(ImageBuffer*); - - WebGraphicsContext3D* context(); - - // Returns the actual context attributes for this drawing buffer which may differ from the - // requested context attributes due to implementation limits. - WebGraphicsContext3D::Attributes getActualAttributes() const { return m_actualAttributes; } - - // WebExternalTextureLayerClient implementation. - virtual bool prepareMailbox(WebExternalTextureMailbox*, WebExternalBitmap*) override; - virtual void mailboxReleased(const WebExternalTextureMailbox&, bool lostResource = false) override; - - // Destroys the TEXTURE_2D binding for the owned context - bool copyToPlatformTexture(WebGraphicsContext3D*, Platform3DObject texture, GLenum internalFormat, - GLenum destType, GLint level, bool premultiplyAlpha, bool flipY, bool fromFrontBuffer = false); - - void setPackAlignment(GLint param); - - void paintRenderingResultsToCanvas(ImageBuffer*); - PassRefPtr paintRenderingResultsToImageData(int&, int&); - -protected: // For unittests - DrawingBuffer( - PassOwnPtr, - PassOwnPtr, - bool multisampleExtensionSupported, - bool packedDepthStencilExtensionSupported, - PreserveDrawingBuffer, - WebGraphicsContext3D::Attributes requestedAttributes, - PassRefPtr); - - bool initialize(const IntSize&); - -private: - void mailboxReleasedWithoutRecycling(const WebExternalTextureMailbox&); - - unsigned createColorTexture(); - // Create the depth/stencil and multisample buffers, if needed. - void createSecondaryBuffers(); - bool resizeFramebuffer(const IntSize&); - bool resizeMultisampleFramebuffer(const IntSize&); - void resizeDepthStencil(const IntSize&); - - // Bind to the m_framebufferBinding if it's not 0. - void restoreFramebufferBinding(); - - void clearPlatformLayer(); - - PassRefPtr recycledMailbox(); - PassRefPtr createNewMailbox(const TextureInfo&); - void deleteMailbox(const WebExternalTextureMailbox&); - void freeRecycledMailboxes(); - - // Updates the current size of the buffer, ensuring that s_currentResourceUsePixels is updated. - void setSize(const IntSize& size); - - // Calculates the difference in pixels between the current buffer size and the proposed size. - static int pixelDelta(const IntSize& newSize, const IntSize& curSize); - - // Given the desired buffer size, provides the largest dimensions that will fit in the pixel budget - // Returns true if the buffer will only fit if the oldest WebGL context is forcibly lost - IntSize adjustSizeWithContextEviction(const IntSize&, bool& evictContext); - - void paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer*); - - // This is the order of bytes to use when doing a readback. - enum ReadbackOrder { - ReadbackRGBA, - ReadbackSkia - }; - - // Helper function which does a readback from the currently-bound - // framebuffer into a buffer of a certain size with 4-byte pixels. - void readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder, WebGLImageConversion::AlphaOp); - - // Helper function to flip a bitmap vertically. - void flipVertically(uint8_t* data, int width, int height); - - // Helper to texImage2D with pixel==0 case: pixels are initialized to 0. - // By default, alignment is 4, the OpenGL default setting. - void texImage2DResourceSafe(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint alignment = 4); - // Allocate buffer storage to be sent to compositor using either texImage2D or CHROMIUM_image based on available support. - void allocateTextureMemory(TextureInfo*, const IntSize&); - void deleteChromiumImageForTexture(TextureInfo*); - - PreserveDrawingBuffer m_preserveDrawingBuffer; - bool m_scissorEnabled; - Platform3DObject m_texture2DBinding; - Platform3DObject m_framebufferBinding; - GLenum m_activeTextureUnit; - - OwnPtr m_context; - OwnPtr m_extensionsUtil; - IntSize m_size; - WebGraphicsContext3D::Attributes m_requestedAttributes; - bool m_multisampleExtensionSupported; - bool m_packedDepthStencilExtensionSupported; - Platform3DObject m_fbo; - // DrawingBuffer's output is double-buffered. m_colorBuffer is the back buffer. - TextureInfo m_colorBuffer; - TextureInfo m_frontColorBuffer; - - // This is used when we have OES_packed_depth_stencil. - Platform3DObject m_depthStencilBuffer; - - // These are used when we don't. - Platform3DObject m_depthBuffer; - Platform3DObject m_stencilBuffer; - - // For multisampling. - Platform3DObject m_multisampleFBO; - Platform3DObject m_multisampleColorBuffer; - - // True if our contents have been modified since the last presentation of this buffer. - bool m_contentsChanged; - - // True if commit() has been called since the last time markContentsChanged() had been called. - bool m_contentsChangeCommitted; - bool m_layerComposited; - - enum MultisampleMode { - None, - ImplicitResolve, - ExplicitResolve, - }; - - MultisampleMode m_multisampleMode; - - WebGraphicsContext3D::Attributes m_actualAttributes; - unsigned m_internalColorFormat; - unsigned m_colorFormat; - unsigned m_internalRenderbufferFormat; - int m_maxTextureSize; - int m_sampleCount; - int m_packAlignment; - bool m_destructionInProgress; - bool m_isHidden; - - OwnPtr m_layer; - - // All of the mailboxes that this DrawingBuffer has ever created. - Vector > m_textureMailboxes; - // Mailboxes that were released by the compositor can be used again by this DrawingBuffer. - Deque m_recycledMailboxQueue; - - RefPtr m_contextEvictionManager; - - // If the width and height of the Canvas's backing store don't - // match those that we were given in the most recent call to - // reshape(), then we need an intermediate bitmap to read back the - // frame buffer into. This seems to happen when CSS styles are - // used to resize the Canvas. - SkBitmap m_resizingBitmap; - - // Used to flip a bitmap vertically. - Vector m_scanline; -}; - -} // namespace blink - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_GPU_DRAWINGBUFFER_H_ diff --git a/engine/platform/graphics/gpu/DrawingBufferTest.cpp b/engine/platform/graphics/gpu/DrawingBufferTest.cpp deleted file mode 100644 index 68454f51b..000000000 --- a/engine/platform/graphics/gpu/DrawingBufferTest.cpp +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Copyright (C) 2013 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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. - */ - - -#include "sky/engine/platform/graphics/gpu/DrawingBuffer.h" - -#include "gen/sky/platform/RuntimeEnabledFeatures.h" -#include "sky/engine/platform/graphics/ImageBuffer.h" -#include "sky/engine/platform/graphics/UnacceleratedImageBufferSurface.h" -#include "sky/engine/platform/graphics/gpu/Extensions3DUtil.h" -#include "sky/engine/platform/graphics/test/MockWebGraphicsContext3D.h" -#include "sky/engine/public/platform/Platform.h" -#include "sky/engine/public/platform/WebExternalTextureMailbox.h" -#include "sky/engine/wtf/RefPtr.h" - -#include -#include - -using namespace blink; -using testing::Test; -using testing::_; - -namespace { - -class FakeContextEvictionManager : public ContextEvictionManager { -public: - void forciblyLoseOldestContext(const String& reason) { } - IntSize oldestContextSize() { return IntSize(); } -}; - -class WebGraphicsContext3DForTests : public MockWebGraphicsContext3D { -public: - WebGraphicsContext3DForTests() - : MockWebGraphicsContext3D() - , m_boundTexture(0) - , m_currentMailboxByte(0) - , m_mostRecentlyWaitedSyncPoint(0) - , m_currentImageId(1) { } - - virtual void bindTexture(WGC3Denum target, WebGLId texture) - { - if (target == GL_TEXTURE_2D) { - m_boundTexture = texture; - } - } - - virtual void texImage2D(WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, WGC3Denum format, WGC3Denum type, const void* pixels) - { - if (target == GL_TEXTURE_2D && !level) { - m_textureSizes.set(m_boundTexture, IntSize(width, height)); - } - } - - virtual void genMailboxCHROMIUM(WGC3Dbyte* mailbox) - { - ++m_currentMailboxByte; - WebExternalTextureMailbox temp; - memset(mailbox, m_currentMailboxByte, sizeof(temp.name)); - } - - virtual void produceTextureDirectCHROMIUM(WebGLId texture, WGC3Denum target, const WGC3Dbyte* mailbox) - { - ASSERT_EQ(target, static_cast(GL_TEXTURE_2D)); - ASSERT_TRUE(m_textureSizes.contains(texture)); - m_mostRecentlyProducedSize = m_textureSizes.get(texture); - } - - IntSize mostRecentlyProducedSize() - { - return m_mostRecentlyProducedSize; - } - - virtual unsigned insertSyncPoint() - { - static unsigned syncPointGenerator = 0; - return ++syncPointGenerator; - } - - virtual void waitSyncPoint(unsigned syncPoint) - { - m_mostRecentlyWaitedSyncPoint = syncPoint; - } - - virtual WGC3Duint createImageCHROMIUM(WGC3Dsizei width, WGC3Dsizei height, WGC3Denum internalformat, WGC3Denum usage) - { - m_imageSizes.set(m_currentImageId, IntSize(width, height)); - return m_currentImageId++; - } - - MOCK_METHOD1(destroyImageMock, void(WGC3Duint imageId)); - void destroyImageCHROMIUM(WGC3Duint imageId) - { - m_imageSizes.remove(imageId); - // No textures should be bound to this. - ASSERT(m_imageToTextureMap.find(imageId) == m_imageToTextureMap.end()); - m_imageSizes.remove(imageId); - destroyImageMock(imageId); - } - - MOCK_METHOD1(bindTexImage2DMock, void(WGC3Dint imageId)); - void bindTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId) - { - if (target == GL_TEXTURE_2D) { - m_textureSizes.set(m_boundTexture, m_imageSizes.find(imageId)->value); - m_imageToTextureMap.set(imageId, m_boundTexture); - bindTexImage2DMock(imageId); - } - } - - MOCK_METHOD1(releaseTexImage2DMock, void(WGC3Dint imageId)); - void releaseTexImage2DCHROMIUM(WGC3Denum target, WGC3Dint imageId) - { - if (target == GL_TEXTURE_2D) { - m_imageSizes.set(m_currentImageId, IntSize()); - m_imageToTextureMap.remove(imageId); - releaseTexImage2DMock(imageId); - } - } - - unsigned mostRecentlyWaitedSyncPoint() - { - return m_mostRecentlyWaitedSyncPoint; - } - - WGC3Duint nextImageIdToBeCreated() - { - return m_currentImageId; - } - -private: - WebGLId m_boundTexture; - HashMap m_textureSizes; - WGC3Dbyte m_currentMailboxByte; - IntSize m_mostRecentlyProducedSize; - unsigned m_mostRecentlyWaitedSyncPoint; - WGC3Duint m_currentImageId; - HashMap m_imageSizes; - HashMap m_imageToTextureMap; -}; - -static const int initialWidth = 100; -static const int initialHeight = 100; -static const int alternateHeight = 50; - -class DrawingBufferForTests : public DrawingBuffer { -public: - static PassRefPtr create(PassOwnPtr context, - const IntSize& size, PreserveDrawingBuffer preserve, PassRefPtr contextEvictionManager) - { - OwnPtr extensionsUtil = Extensions3DUtil::create(context.get()); - RefPtr drawingBuffer = - adoptRef(new DrawingBufferForTests(context, extensionsUtil.release(), preserve, contextEvictionManager)); - if (!drawingBuffer->initialize(size)) { - drawingBuffer->beginDestruction(); - return PassRefPtr(); - } - return drawingBuffer.release(); - } - - DrawingBufferForTests(PassOwnPtr context, - PassOwnPtr extensionsUtil, - PreserveDrawingBuffer preserve, - PassRefPtr contextEvictionManager) - : DrawingBuffer(context, extensionsUtil, false /* multisampleExtensionSupported */, - false /* packedDepthStencilExtensionSupported */, preserve, WebGraphicsContext3D::Attributes(), contextEvictionManager) - , m_live(0) - { } - - virtual ~DrawingBufferForTests() - { - if (m_live) - *m_live = false; - } - - bool* m_live; -}; - -class DrawingBufferTest : public Test { -protected: - void SetUp() override - { - RefPtr contextEvictionManager = adoptRef(new FakeContextEvictionManager()); - OwnPtr context = adoptPtr(new WebGraphicsContext3DForTests); - m_context = context.get(); - m_drawingBuffer = DrawingBufferForTests::create(context.release(), - IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve, contextEvictionManager.release()); - } - - WebGraphicsContext3DForTests* webContext() - { - return m_context; - } - - WebGraphicsContext3DForTests* m_context; - RefPtr m_drawingBuffer; -}; - -TEST_F(DrawingBufferTest, testPaintRenderingResultsToCanvas) -{ - OwnPtr imageBufferSurface = adoptPtr(new UnacceleratedImageBufferSurface(IntSize(initialWidth, initialHeight))); - EXPECT_FALSE(!imageBufferSurface); - EXPECT_TRUE(imageBufferSurface->isValid()); - OwnPtr imageBuffer = ImageBuffer::create(imageBufferSurface.release()); - EXPECT_FALSE(!imageBuffer); - EXPECT_FALSE(imageBuffer->isAccelerated()); - EXPECT_FALSE(imageBuffer->bitmap().isNull()); - m_drawingBuffer->paintRenderingResultsToCanvas(imageBuffer.get()); - EXPECT_FALSE(imageBuffer->isAccelerated()); - EXPECT_FALSE(imageBuffer->bitmap().isNull()); - m_drawingBuffer->beginDestruction(); -} - -TEST_F(DrawingBufferTest, verifyResizingProperlyAffectsMailboxes) -{ - WebExternalTextureMailbox mailbox; - - IntSize initialSize(initialWidth, initialHeight); - IntSize alternateSize(initialWidth, alternateHeight); - - // Produce one mailbox at size 100x100. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); - - // Resize to 100x50. - m_drawingBuffer->reset(IntSize(initialWidth, alternateHeight)); - m_drawingBuffer->mailboxReleased(mailbox, false); - - // Produce a mailbox at this size. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(alternateSize, webContext()->mostRecentlyProducedSize()); - - // Reset to initial size. - m_drawingBuffer->reset(IntSize(initialWidth, initialHeight)); - m_drawingBuffer->mailboxReleased(mailbox, false); - - // Prepare another mailbox and verify that it's the correct size. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); - - // Prepare one final mailbox and verify that it's the correct size. - m_drawingBuffer->mailboxReleased(mailbox, false); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); - m_drawingBuffer->beginDestruction(); -} - -TEST_F(DrawingBufferTest, verifyDestructionCompleteAfterAllMailboxesReleased) -{ - bool live = true; - m_drawingBuffer->m_live = &live; - - WebExternalTextureMailbox mailbox1; - WebExternalTextureMailbox mailbox2; - WebExternalTextureMailbox mailbox3; - - IntSize initialSize(initialWidth, initialHeight); - - // Produce mailboxes. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox1, 0)); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox2, 0)); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox3, 0)); - - m_drawingBuffer->markContentsChanged(); - m_drawingBuffer->mailboxReleased(mailbox1, false); - - m_drawingBuffer->beginDestruction(); - EXPECT_EQ(live, true); - - DrawingBufferForTests* weakPointer = m_drawingBuffer.get(); - m_drawingBuffer.clear(); - EXPECT_EQ(live, true); - - weakPointer->markContentsChanged(); - weakPointer->mailboxReleased(mailbox2, false); - EXPECT_EQ(live, true); - - weakPointer->markContentsChanged(); - weakPointer->mailboxReleased(mailbox3, false); - EXPECT_EQ(live, false); -} - -TEST_F(DrawingBufferTest, verifyDrawingBufferStaysAliveIfResourcesAreLost) -{ - bool live = true; - m_drawingBuffer->m_live = &live; - WebExternalTextureMailbox mailbox1; - WebExternalTextureMailbox mailbox2; - WebExternalTextureMailbox mailbox3; - - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox1, 0)); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox2, 0)); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox3, 0)); - - m_drawingBuffer->markContentsChanged(); - m_drawingBuffer->mailboxReleased(mailbox1, true); - EXPECT_EQ(live, true); - - m_drawingBuffer->beginDestruction(); - EXPECT_EQ(live, true); - - m_drawingBuffer->markContentsChanged(); - m_drawingBuffer->mailboxReleased(mailbox2, false); - EXPECT_EQ(live, true); - - DrawingBufferForTests* weakPtr = m_drawingBuffer.get(); - m_drawingBuffer.clear(); - EXPECT_EQ(live, true); - - weakPtr->markContentsChanged(); - weakPtr->mailboxReleased(mailbox3, true); - EXPECT_EQ(live, false); -} - -class TextureMailboxWrapper { -public: - explicit TextureMailboxWrapper(const WebExternalTextureMailbox& mailbox) - : m_mailbox(mailbox) - { } - - bool operator==(const TextureMailboxWrapper& other) const - { - return !memcmp(m_mailbox.name, other.m_mailbox.name, sizeof(m_mailbox.name)); - } - - bool operator!=(const TextureMailboxWrapper& other) const - { - return !(*this == other); - } - -private: - WebExternalTextureMailbox m_mailbox; -}; - -TEST_F(DrawingBufferTest, verifyOnlyOneRecycledMailboxMustBeKept) -{ - WebExternalTextureMailbox mailbox1; - WebExternalTextureMailbox mailbox2; - WebExternalTextureMailbox mailbox3; - - // Produce mailboxes. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox1, 0)); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox2, 0)); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox3, 0)); - - // Release mailboxes by specific order; 1, 3, 2. - m_drawingBuffer->markContentsChanged(); - m_drawingBuffer->mailboxReleased(mailbox1, false); - m_drawingBuffer->markContentsChanged(); - m_drawingBuffer->mailboxReleased(mailbox3, false); - m_drawingBuffer->markContentsChanged(); - m_drawingBuffer->mailboxReleased(mailbox2, false); - - // The first recycled mailbox must be 2. 1 and 3 were deleted by FIFO order because - // DrawingBuffer never keeps more than one mailbox. - WebExternalTextureMailbox recycledMailbox1; - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox1, 0)); - EXPECT_EQ(TextureMailboxWrapper(mailbox2), TextureMailboxWrapper(recycledMailbox1)); - - // The second recycled mailbox must be a new mailbox. - WebExternalTextureMailbox recycledMailbox2; - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&recycledMailbox2, 0)); - EXPECT_NE(TextureMailboxWrapper(mailbox1), TextureMailboxWrapper(recycledMailbox2)); - EXPECT_NE(TextureMailboxWrapper(mailbox2), TextureMailboxWrapper(recycledMailbox2)); - EXPECT_NE(TextureMailboxWrapper(mailbox3), TextureMailboxWrapper(recycledMailbox2)); - - m_drawingBuffer->mailboxReleased(recycledMailbox1, false); - m_drawingBuffer->mailboxReleased(recycledMailbox2, false); - m_drawingBuffer->beginDestruction(); -} - -TEST_F(DrawingBufferTest, verifyInsertAndWaitSyncPointCorrectly) -{ - WebExternalTextureMailbox mailbox; - - // Produce mailboxes. - m_drawingBuffer->markContentsChanged(); - EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint()); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - // prepareMailbox() does not wait for any sync point. - EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint()); - - unsigned waitSyncPoint = webContext()->insertSyncPoint(); - mailbox.syncPoint = waitSyncPoint; - m_drawingBuffer->mailboxReleased(mailbox, false); - // m_drawingBuffer will wait for the sync point when recycling. - EXPECT_EQ(0u, webContext()->mostRecentlyWaitedSyncPoint()); - - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - // m_drawingBuffer waits for the sync point when recycling in prepareMailbox(). - EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint()); - - m_drawingBuffer->beginDestruction(); - waitSyncPoint = webContext()->insertSyncPoint(); - mailbox.syncPoint = waitSyncPoint; - m_drawingBuffer->mailboxReleased(mailbox, false); - // m_drawingBuffer waits for the sync point because the destruction is in progress. - EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint()); -} - -class DrawingBufferImageChromiumTest : public DrawingBufferTest { -protected: - void SetUp() override - { - RefPtr contextEvictionManager = adoptRef(new FakeContextEvictionManager()); - OwnPtr context = adoptPtr(new WebGraphicsContext3DForTests); - m_context = context.get(); - RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(true); - m_imageId0 = webContext()->nextImageIdToBeCreated(); - EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId0)).Times(1); - m_drawingBuffer = DrawingBufferForTests::create(context.release(), - IntSize(initialWidth, initialHeight), DrawingBuffer::Preserve, contextEvictionManager.release()); - testing::Mock::VerifyAndClearExpectations(webContext()); - } - - void TearDown() override - { - RuntimeEnabledFeatures::setWebGLImageChromiumEnabled(false); - } - WGC3Duint m_imageId0; -}; - -TEST_F(DrawingBufferImageChromiumTest, verifyResizingReallocatesImages) -{ - WebExternalTextureMailbox mailbox; - - IntSize initialSize(initialWidth, initialHeight); - IntSize alternateSize(initialWidth, alternateHeight); - - WGC3Duint m_imageId1 = webContext()->nextImageIdToBeCreated(); - EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId1)).Times(1); - // Produce one mailbox at size 100x100. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); - EXPECT_TRUE(mailbox.allowOverlay); - testing::Mock::VerifyAndClearExpectations(webContext()); - - WGC3Duint m_imageId2 = webContext()->nextImageIdToBeCreated(); - EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId2)).Times(1); - EXPECT_CALL(*webContext(), destroyImageMock(m_imageId0)).Times(1); - EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId0)).Times(1); - // Resize to 100x50. - m_drawingBuffer->reset(IntSize(initialWidth, alternateHeight)); - m_drawingBuffer->mailboxReleased(mailbox, false); - testing::Mock::VerifyAndClearExpectations(webContext()); - - WGC3Duint m_imageId3 = webContext()->nextImageIdToBeCreated(); - EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId3)).Times(1); - EXPECT_CALL(*webContext(), destroyImageMock(m_imageId1)).Times(1); - EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId1)).Times(1); - // Produce a mailbox at this size. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(alternateSize, webContext()->mostRecentlyProducedSize()); - EXPECT_TRUE(mailbox.allowOverlay); - testing::Mock::VerifyAndClearExpectations(webContext()); - - WGC3Duint m_imageId4 = webContext()->nextImageIdToBeCreated(); - EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId4)).Times(1); - EXPECT_CALL(*webContext(), destroyImageMock(m_imageId2)).Times(1); - EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId2)).Times(1); - // Reset to initial size. - m_drawingBuffer->reset(IntSize(initialWidth, initialHeight)); - m_drawingBuffer->mailboxReleased(mailbox, false); - testing::Mock::VerifyAndClearExpectations(webContext()); - - WGC3Duint m_imageId5 = webContext()->nextImageIdToBeCreated(); - EXPECT_CALL(*webContext(), bindTexImage2DMock(m_imageId5)).Times(1); - EXPECT_CALL(*webContext(), destroyImageMock(m_imageId3)).Times(1); - EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId3)).Times(1); - // Prepare another mailbox and verify that it's the correct size. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); - EXPECT_TRUE(mailbox.allowOverlay); - testing::Mock::VerifyAndClearExpectations(webContext()); - - // Prepare one final mailbox and verify that it's the correct size. - m_drawingBuffer->mailboxReleased(mailbox, false); - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - EXPECT_EQ(initialSize, webContext()->mostRecentlyProducedSize()); - EXPECT_TRUE(mailbox.allowOverlay); - m_drawingBuffer->mailboxReleased(mailbox, false); - - EXPECT_CALL(*webContext(), destroyImageMock(m_imageId5)).Times(1); - EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId5)).Times(1); - EXPECT_CALL(*webContext(), destroyImageMock(m_imageId4)).Times(1); - EXPECT_CALL(*webContext(), releaseTexImage2DMock(m_imageId4)).Times(1); - m_drawingBuffer->beginDestruction(); - testing::Mock::VerifyAndClearExpectations(webContext()); -} - -class DepthStencilTrackingContext : public MockWebGraphicsContext3D { -public: - DepthStencilTrackingContext() - : m_nextRenderBufferId(1) - , m_stencilAttachment(0) - , m_depthAttachment(0) { } - virtual ~DepthStencilTrackingContext() { } - - int numAllocatedRenderBuffer() const { return m_nextRenderBufferId - 1; } - WebGLId stencilAttachment() const { return m_stencilAttachment; } - WebGLId depthAttachment() const { return m_depthAttachment; } - - virtual WebString getString(WGC3Denum type) override - { - if (type == GL_EXTENSIONS) { - return WebString::fromUTF8("GL_OES_packed_depth_stencil"); - } - return WebString(); - } - - virtual WebGLId createRenderbuffer() override - { - return ++m_nextRenderBufferId; - } - - virtual void framebufferRenderbuffer(WGC3Denum target, WGC3Denum attachment, WGC3Denum renderbuffertarget, WebGLId renderbuffer) override - { - if (attachment == GL_STENCIL_ATTACHMENT) { - m_stencilAttachment = renderbuffer; - } else { - m_depthAttachment = renderbuffer; - } - } - - virtual void getIntegerv(WGC3Denum ptype, WGC3Dint* value) override - { - switch (ptype) { - case GL_DEPTH_BITS: - *value = m_depthAttachment ? 24 : 0; - return; - case GL_STENCIL_BITS: - *value = m_stencilAttachment ? 8 : 0; - return; - } - MockWebGraphicsContext3D::getIntegerv(ptype, value); - } - -private: - WebGLId m_nextRenderBufferId; - WebGLId m_stencilAttachment; - WebGLId m_depthAttachment; -}; - -struct DepthStencilTestCase { - DepthStencilTestCase(bool requestStencil, bool requestDepth, int expectedRenderBuffers, bool expectDepthStencil, const char* const testCaseName) - : requestStencil(requestStencil) - , requestDepth(requestDepth) - , expectDepthStencil(expectDepthStencil) - , expectedRenderBuffers(expectedRenderBuffers) - , testCaseName(testCaseName) { } - - bool requestStencil; - bool requestDepth; - bool expectDepthStencil; - int expectedRenderBuffers; - const char* const testCaseName; -}; - -// This tests that when the packed depth+stencil extension is supported DrawingBuffer always allocates -// a single packed renderbuffer if either is requested and properly computes the actual context attributes -// as defined by WebGL. We always allocate a packed buffer in this case since many desktop OpenGL drivers -// that support this extension do not consider a framebuffer with only a depth or a stencil buffer attached -// to be complete. -TEST(DrawingBufferDepthStencilTest, packedDepthStencilSupported) -{ - DepthStencilTestCase cases[] = { - DepthStencilTestCase(false, false, false, 0, "neither"), - DepthStencilTestCase(true, false, true, 1, "stencil only"), - DepthStencilTestCase(false, true, true, 1, "depth only"), - DepthStencilTestCase(true, true, true, 1, "both"), - }; - - for (size_t i = 0; i < arraysize(cases); i++) { - SCOPED_TRACE(cases[i].testCaseName); - OwnPtr context = adoptPtr(new DepthStencilTrackingContext); - DepthStencilTrackingContext* trackingContext = context.get(); - DrawingBuffer::PreserveDrawingBuffer preserve = DrawingBuffer::Preserve; - RefPtr contextEvictionManager = adoptRef(new FakeContextEvictionManager); - - WebGraphicsContext3D::Attributes requestedAttributes; - requestedAttributes.stencil = cases[i].requestStencil; - requestedAttributes.depth = cases[i].requestDepth; - RefPtr drawingBuffer = DrawingBuffer::create(context.release(), IntSize(10, 10), preserve, requestedAttributes, contextEvictionManager); - - EXPECT_EQ(cases[i].requestDepth, drawingBuffer->getActualAttributes().depth); - EXPECT_EQ(cases[i].requestStencil, drawingBuffer->getActualAttributes().stencil); - EXPECT_EQ(cases[i].expectedRenderBuffers, trackingContext->numAllocatedRenderBuffer()); - if (cases[i].expectDepthStencil) { - EXPECT_EQ(trackingContext->stencilAttachment(), trackingContext->depthAttachment()); - } else if (cases[i].requestStencil || cases[i].requestDepth) { - EXPECT_NE(trackingContext->stencilAttachment(), trackingContext->depthAttachment()); - } else { - EXPECT_EQ(0u, trackingContext->stencilAttachment()); - EXPECT_EQ(0u, trackingContext->depthAttachment()); - } - - drawingBuffer->reset(IntSize(10, 20)); - EXPECT_EQ(cases[i].requestDepth, drawingBuffer->getActualAttributes().depth); - EXPECT_EQ(cases[i].requestStencil, drawingBuffer->getActualAttributes().stencil); - EXPECT_EQ(cases[i].expectedRenderBuffers, trackingContext->numAllocatedRenderBuffer()); - if (cases[i].expectDepthStencil) { - EXPECT_EQ(trackingContext->stencilAttachment(), trackingContext->depthAttachment()); - } else if (cases[i].requestStencil || cases[i].requestDepth) { - EXPECT_NE(trackingContext->stencilAttachment(), trackingContext->depthAttachment()); - } else { - EXPECT_EQ(0u, trackingContext->stencilAttachment()); - EXPECT_EQ(0u, trackingContext->depthAttachment()); - } - - drawingBuffer->beginDestruction(); - } -} - -TEST_F(DrawingBufferTest, verifySetIsHiddenProperlyAffectsMailboxes) -{ - blink::WebExternalTextureMailbox mailbox; - - // Produce mailboxes. - m_drawingBuffer->markContentsChanged(); - EXPECT_TRUE(m_drawingBuffer->prepareMailbox(&mailbox, 0)); - - unsigned waitSyncPoint = webContext()->insertSyncPoint(); - mailbox.syncPoint = waitSyncPoint; - m_drawingBuffer->setIsHidden(true); - m_drawingBuffer->mailboxReleased(mailbox); - // m_drawingBuffer deletes mailbox immediately when hidden. - EXPECT_EQ(waitSyncPoint, webContext()->mostRecentlyWaitedSyncPoint()); - - m_drawingBuffer->beginDestruction(); -} - -} // namespace diff --git a/engine/platform/graphics/gpu/Extensions3DUtil.cpp b/engine/platform/graphics/gpu/Extensions3DUtil.cpp deleted file mode 100644 index bcc650279..000000000 --- a/engine/platform/graphics/gpu/Extensions3DUtil.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sky/engine/platform/graphics/gpu/Extensions3DUtil.h" - -#include "sky/engine/public/platform/WebGraphicsContext3D.h" -#include "sky/engine/wtf/PassOwnPtr.h" -#include "sky/engine/wtf/text/CString.h" -#include "sky/engine/wtf/text/StringHash.h" - -namespace blink { - -namespace { - -void splitStringHelper(const String& str, HashSet& set) -{ - Vector substrings; - str.split(' ', substrings); - for (size_t i = 0; i < substrings.size(); ++i) - set.add(substrings[i]); -} - -} // anonymous namespace - -PassOwnPtr Extensions3DUtil::create(WebGraphicsContext3D* context) -{ - OwnPtr out = adoptPtr(new Extensions3DUtil(context)); - if (!out->initializeExtensions()) - return nullptr; - return out.release(); -} - -Extensions3DUtil::Extensions3DUtil(WebGraphicsContext3D* context) - : m_context(context) -{ -} - -Extensions3DUtil::~Extensions3DUtil() -{ -} - -bool Extensions3DUtil::initializeExtensions() -{ - if (m_context->isContextLost()) { - // Need to try to restore the context again later. - return false; - } - - String extensionsString = m_context->getString(GL_EXTENSIONS); - splitStringHelper(extensionsString, m_enabledExtensions); - - String requestableExtensionsString = m_context->getRequestableExtensionsCHROMIUM(); - splitStringHelper(requestableExtensionsString, m_requestableExtensions); - - return true; -} - - -bool Extensions3DUtil::supportsExtension(const String& name) -{ - return m_enabledExtensions.contains(name) || m_requestableExtensions.contains(name); -} - -bool Extensions3DUtil::ensureExtensionEnabled(const String& name) -{ - if (m_enabledExtensions.contains(name)) - return true; - - if (m_requestableExtensions.contains(name)) { - m_context->requestExtensionCHROMIUM(name.ascii().data()); - m_enabledExtensions.clear(); - m_requestableExtensions.clear(); - initializeExtensions(); - } - return m_enabledExtensions.contains(name); -} - -bool Extensions3DUtil::isExtensionEnabled(const String& name) -{ - return m_enabledExtensions.contains(name); -} - -bool Extensions3DUtil::canUseCopyTextureCHROMIUM(GLenum destFormat, GLenum destType, GLint level) -{ - // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE/(Level 0) should be lifted when - // WebGraphicsContext3D::copyTextureCHROMIUM(...) are fully functional. - if ((destFormat == GL_RGB || destFormat == GL_RGBA) - && destType == GL_UNSIGNED_BYTE - && !level) - return true; - return false; -} - -} // namespace blink diff --git a/engine/platform/graphics/gpu/Extensions3DUtil.h b/engine/platform/graphics/gpu/Extensions3DUtil.h deleted file mode 100644 index e8c95a0fe..000000000 --- a/engine/platform/graphics/gpu/Extensions3DUtil.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SKY_ENGINE_PLATFORM_GRAPHICS_GPU_EXTENSIONS3DUTIL_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_GPU_EXTENSIONS3DUTIL_H_ - -#include "sky/engine/platform/PlatformExport.h" -#include "sky/engine/platform/graphics/GraphicsTypes3D.h" -#include "sky/engine/wtf/HashSet.h" -#include "sky/engine/wtf/text/WTFString.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" - -namespace blink { - -class WebGraphicsContext3D; - -class PLATFORM_EXPORT Extensions3DUtil { -public: - // Creates a new Extensions3DUtil. If the passed WebGraphicsContext3D has been spontaneously lost, returns null. - static PassOwnPtr create(WebGraphicsContext3D*); - ~Extensions3DUtil(); - - bool supportsExtension(const String& name); - bool ensureExtensionEnabled(const String& name); - bool isExtensionEnabled(const String& name); - - static bool canUseCopyTextureCHROMIUM(GLenum destFormat, GLenum destType, GLint level); - -private: - Extensions3DUtil(WebGraphicsContext3D*); - bool initializeExtensions(); - - WebGraphicsContext3D* m_context; - HashSet m_enabledExtensions; - HashSet m_requestableExtensions; -}; - -} // namespace blink - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_GPU_EXTENSIONS3DUTIL_H_ diff --git a/engine/platform/graphics/gpu/WebGLImageBufferSurface.cpp b/engine/platform/graphics/gpu/WebGLImageBufferSurface.cpp deleted file mode 100644 index f4b142a31..000000000 --- a/engine/platform/graphics/gpu/WebGLImageBufferSurface.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2013, 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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. - */ - - -#include "sky/engine/platform/graphics/gpu/WebGLImageBufferSurface.h" - -#include "sky/engine/platform/graphics/skia/GaneshUtils.h" -#include "sky/engine/public/platform/Platform.h" -#include "sky/engine/public/platform/WebGraphicsContext3DProvider.h" -#include "sky/engine/wtf/PassOwnPtr.h" -#include "third_party/skia/include/core/SkPixelRef.h" - -namespace blink { - -WebGLImageBufferSurface::WebGLImageBufferSurface(const IntSize& size, OpacityMode opacityMode) - : ImageBufferSurface(size, opacityMode) -{ - m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); - if (!m_contextProvider) - return; - GrContext* gr = m_contextProvider->grContext(); - if (!gr) - return; - ensureTextureBackedSkBitmap(gr, m_bitmap, size, kDefault_GrSurfaceOrigin, kRGBA_8888_GrPixelConfig); -} - -WebGLImageBufferSurface::~WebGLImageBufferSurface() -{ -} - -Platform3DObject WebGLImageBufferSurface::getBackingTexture() const -{ - GrTexture* texture = m_bitmap.getTexture(); - if (!texture) - return 0; - return texture->getTextureHandle(); -} - -void WebGLImageBufferSurface::invalidateCachedBitmap() -{ - m_cachedBitmap.reset(); -} - -void WebGLImageBufferSurface::updateCachedBitmapIfNeeded() -{ - if (m_cachedBitmap.isNull() && m_bitmap.pixelRef()) { - (m_bitmap.pixelRef())->readPixels(&m_cachedBitmap); - } -} - -} // namespace blink diff --git a/engine/platform/graphics/gpu/WebGLImageBufferSurface.h b/engine/platform/graphics/gpu/WebGLImageBufferSurface.h deleted file mode 100644 index 533a4d87e..000000000 --- a/engine/platform/graphics/gpu/WebGLImageBufferSurface.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2013, 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * 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. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT - * OWNER OR 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 SKY_ENGINE_PLATFORM_GRAPHICS_GPU_WEBGLIMAGEBUFFERSURFACE_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_GPU_WEBGLIMAGEBUFFERSURFACE_H_ - -#include "sky/engine/platform/graphics/ImageBufferSurface.h" -#include "sky/engine/wtf/OwnPtr.h" -#include "third_party/skia/include/core/SkBitmap.h" - -namespace blink { - -class WebGraphicsContext3DProvider; - -// This is a GPU backed surface that has no canvas or render target. -class PLATFORM_EXPORT WebGLImageBufferSurface : public ImageBufferSurface { - WTF_MAKE_NONCOPYABLE(WebGLImageBufferSurface); WTF_MAKE_FAST_ALLOCATED; -public: - WebGLImageBufferSurface(const IntSize&, OpacityMode = NonOpaque); - virtual ~WebGLImageBufferSurface(); - - virtual SkCanvas* canvas() const override { return 0; } - virtual const SkBitmap& bitmap() override { return m_bitmap; } - virtual bool isValid() const override { return m_bitmap.pixelRef(); } - virtual bool isAccelerated() const override { return true; } - virtual Platform3DObject getBackingTexture() const override; - virtual bool cachedBitmapEnabled() const override { return true; } - virtual const SkBitmap& cachedBitmap() const override { return m_cachedBitmap; } - virtual void invalidateCachedBitmap() override; - virtual void updateCachedBitmapIfNeeded() override; - -private: - SkBitmap m_bitmap; - // This raw-pixel based SkBitmap works as a cache at CPU side to avoid heavy cost - // on readback from GPU side to CPU side in some cases. - SkBitmap m_cachedBitmap; - OwnPtr m_contextProvider; -}; - -} // namespace blink - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_GPU_WEBGLIMAGEBUFFERSURFACE_H_ diff --git a/engine/platform/graphics/gpu/WebGLImageConversion.cpp b/engine/platform/graphics/gpu/WebGLImageConversion.cpp deleted file mode 100644 index 692b5923d..000000000 --- a/engine/platform/graphics/gpu/WebGLImageConversion.cpp +++ /dev/null @@ -1,1778 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sky/engine/platform/graphics/gpu/WebGLImageConversion.h" - -#include "platform/image-decoders/ImageDecoder.h" -#include "sky/engine/platform/CheckedInt.h" -#include "sky/engine/platform/graphics/ImageObserver.h" -#include "sky/engine/platform/graphics/cpu/arm/WebGLImageConversionNEON.h" -#include "sky/engine/wtf/OwnPtr.h" -#include "sky/engine/wtf/PassOwnPtr.h" - -namespace blink { - -namespace { - -WebGLImageConversion::DataFormat getDataFormat(GLenum destinationFormat, GLenum destinationType) -{ - WebGLImageConversion::DataFormat dstFormat = WebGLImageConversion::DataFormatRGBA8; - switch (destinationType) { - case GL_UNSIGNED_BYTE: - switch (destinationFormat) { - case GL_RGB: - dstFormat = WebGLImageConversion::DataFormatRGB8; - break; - case GL_RGBA: - dstFormat = WebGLImageConversion::DataFormatRGBA8; - break; - case GL_ALPHA: - dstFormat = WebGLImageConversion::DataFormatA8; - break; - case GL_LUMINANCE: - dstFormat = WebGLImageConversion::DataFormatR8; - break; - case GL_LUMINANCE_ALPHA: - dstFormat = WebGLImageConversion::DataFormatRA8; - break; - default: - ASSERT_NOT_REACHED(); - } - break; - case GL_UNSIGNED_SHORT_4_4_4_4: - dstFormat = WebGLImageConversion::DataFormatRGBA4444; - break; - case GL_UNSIGNED_SHORT_5_5_5_1: - dstFormat = WebGLImageConversion::DataFormatRGBA5551; - break; - case GL_UNSIGNED_SHORT_5_6_5: - dstFormat = WebGLImageConversion::DataFormatRGB565; - break; - case GL_HALF_FLOAT_OES: // OES_texture_half_float - switch (destinationFormat) { - case GL_RGB: - dstFormat = WebGLImageConversion::DataFormatRGB16F; - break; - case GL_RGBA: - dstFormat = WebGLImageConversion::DataFormatRGBA16F; - break; - case GL_ALPHA: - dstFormat = WebGLImageConversion::DataFormatA16F; - break; - case GL_LUMINANCE: - dstFormat = WebGLImageConversion::DataFormatR16F; - break; - case GL_LUMINANCE_ALPHA: - dstFormat = WebGLImageConversion::DataFormatRA16F; - break; - default: - ASSERT_NOT_REACHED(); - } - break; - case GL_FLOAT: // OES_texture_float - switch (destinationFormat) { - case GL_RGB: - dstFormat = WebGLImageConversion::DataFormatRGB32F; - break; - case GL_RGBA: - dstFormat = WebGLImageConversion::DataFormatRGBA32F; - break; - case GL_ALPHA: - dstFormat = WebGLImageConversion::DataFormatA32F; - break; - case GL_LUMINANCE: - dstFormat = WebGLImageConversion::DataFormatR32F; - break; - case GL_LUMINANCE_ALPHA: - dstFormat = WebGLImageConversion::DataFormatRA32F; - break; - default: - ASSERT_NOT_REACHED(); - } - break; - default: - ASSERT_NOT_REACHED(); - } - return dstFormat; -} - -// Following Float to Half-Float converion code is from the implementation of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf, -// "Fast Half Float Conversions" by Jeroen van der Zijp, November 2008 (Revised September 2010). -// Specially, the basetable[512] and shifttable[512] are generated as follows: -/* -unsigned short basetable[512]; -unsigned char shifttable[512]; - -void generatetables(){ - unsigned int i; - int e; - for (i = 0; i < 256; ++i){ - e = i - 127; - if (e < -24){ // Very small numbers map to zero - basetable[i | 0x000] = 0x0000; - basetable[i | 0x100] = 0x8000; - shifttable[i | 0x000] = 24; - shifttable[i | 0x100] = 24; - } - else if (e < -14) { // Small numbers map to denorms - basetable[i | 0x000] = (0x0400>>(-e-14)); - basetable[i | 0x100] = (0x0400>>(-e-14)) | 0x8000; - shifttable[i | 0x000] = -e-1; - shifttable[i | 0x100] = -e-1; - } - else if (e <= 15){ // Normal numbers just lose precision - basetable[i | 0x000] = ((e+15)<<10); - basetable[i| 0x100] = ((e+15)<<10) | 0x8000; - shifttable[i|0x000] = 13; - shifttable[i|0x100] = 13; - } - else if (e<128){ // Large numbers map to Infinity - basetable[i|0x000] = 0x7C00; - basetable[i|0x100] = 0xFC00; - shifttable[i|0x000] = 24; - shifttable[i|0x100] = 24; - } - else { // Infinity and NaN's stay Infinity and NaN's - basetable[i|0x000] = 0x7C00; - basetable[i|0x100] = 0xFC00; - shifttable[i|0x000] = 13; - shifttable[i|0x100] = 13; - } - } -} -*/ - -unsigned short baseTable[512] = { -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, -512, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, -16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720, 31744, -31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, -31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, -31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, -31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, -31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, -31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, -31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, 31744, -32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, -32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, -32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, -32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, -32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, -32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, 32768, -32768, 32768, 32768, 32768, 32768, 32768, 32768, 32769, 32770, 32772, 32776, 32784, 32800, 32832, 32896, 33024, -33280, 33792, 34816, 35840, 36864, 37888, 38912, 39936, 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128, -49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320, 57344, 58368, 59392, 60416, 61440, 62464, 63488, 64512, -64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, -64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, -64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, -64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, -64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, -64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, -64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512 -}; - -unsigned char shiftTable[512] = { -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, -14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, -14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 13 -}; - -unsigned short convertFloatToHalfFloat(float f) -{ - unsigned temp = *(reinterpret_cast(&f)); - unsigned signexp = (temp >> 23) & 0x1ff; - return baseTable[signexp] + ((temp & 0x007fffff) >> shiftTable[signexp]); -} - -/* BEGIN CODE SHARED WITH MOZILLA FIREFOX */ - -// The following packing and unpacking routines are expressed in terms of function templates and inline functions to achieve generality and speedup. -// Explicit template specializations correspond to the cases that would occur. -// Some code are merged back from Mozilla code in http://mxr.mozilla.org/mozilla-central/source/content/canvas/src/WebGLTexelConversions.h - -//---------------------------------------------------------------------- -// Pixel unpacking routines. -template -void unpack(const SourceType*, DstType*, unsigned) -{ - ASSERT_NOT_REACHED(); -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[1]; - destination[2] = source[2]; - destination[3] = 0xFF; - source += 3; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[2]; - destination[1] = source[1]; - destination[2] = source[0]; - destination[3] = 0xFF; - source += 3; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[1]; - destination[1] = source[2]; - destination[2] = source[3]; - destination[3] = source[0]; - source += 4; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[3]; - destination[1] = source[2]; - destination[2] = source[1]; - destination[3] = source[0]; - source += 4; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - const uint32_t* source32 = reinterpret_cast_ptr(source); - uint32_t* destination32 = reinterpret_cast_ptr(destination); - for (unsigned i = 0; i < pixelsPerRow; ++i) { - uint32_t bgra = source32[i]; -#if CPU(BIG_ENDIAN) - uint32_t brMask = 0xff00ff00; - uint32_t gaMask = 0x00ff00ff; -#else - uint32_t brMask = 0x00ff00ff; - uint32_t gaMask = 0xff00ff00; -#endif - uint32_t rgba = (((bgra >> 16) | (bgra << 16)) & brMask) | (bgra & gaMask); - destination32[i] = rgba; - } -} - -template<> void unpack(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ -#if HAVE(ARM_NEON_INTRINSICS) - SIMD::unpackOneRowOfRGBA5551ToRGBA8(source, destination, pixelsPerRow); -#endif - for (unsigned i = 0; i < pixelsPerRow; ++i) { - uint16_t packedValue = source[0]; - uint8_t r = packedValue >> 11; - uint8_t g = (packedValue >> 6) & 0x1F; - uint8_t b = (packedValue >> 1) & 0x1F; - destination[0] = (r << 3) | (r & 0x7); - destination[1] = (g << 3) | (g & 0x7); - destination[2] = (b << 3) | (b & 0x7); - destination[3] = (packedValue & 0x1) ? 0xFF : 0x0; - source += 1; - destination += 4; - } -} - -template<> void unpack(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ -#if HAVE(ARM_NEON_INTRINSICS) - SIMD::unpackOneRowOfRGBA4444ToRGBA8(source, destination, pixelsPerRow); -#endif - for (unsigned i = 0; i < pixelsPerRow; ++i) { - uint16_t packedValue = source[0]; - uint8_t r = packedValue >> 12; - uint8_t g = (packedValue >> 8) & 0x0F; - uint8_t b = (packedValue >> 4) & 0x0F; - uint8_t a = packedValue & 0x0F; - destination[0] = r << 4 | r; - destination[1] = g << 4 | g; - destination[2] = b << 4 | b; - destination[3] = a << 4 | a; - source += 1; - destination += 4; - } -} - -template<> void unpack(const uint16_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ -#if HAVE(ARM_NEON_INTRINSICS) - SIMD::unpackOneRowOfRGB565ToRGBA8(source, destination, pixelsPerRow); -#endif - for (unsigned i = 0; i < pixelsPerRow; ++i) { - uint16_t packedValue = source[0]; - uint8_t r = packedValue >> 11; - uint8_t g = (packedValue >> 5) & 0x3F; - uint8_t b = packedValue & 0x1F; - destination[0] = (r << 3) | (r & 0x7); - destination[1] = (g << 2) | (g & 0x3); - destination[2] = (b << 3) | (b & 0x7); - destination[3] = 0xFF; - source += 1; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[0]; - destination[2] = source[0]; - destination[3] = 0xFF; - source += 1; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[0]; - destination[2] = source[0]; - destination[3] = source[1]; - source += 2; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[1]; - destination[1] = source[1]; - destination[2] = source[1]; - destination[3] = source[0]; - source += 2; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = 0x0; - destination[1] = 0x0; - destination[2] = 0x0; - destination[3] = source[0]; - source += 1; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, float* destination, unsigned pixelsPerRow) -{ - const float scaleFactor = 1.0f / 255.0f; - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[2] * scaleFactor; - destination[3] = source[3] * scaleFactor; - source += 4; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, float* destination, unsigned pixelsPerRow) -{ - const float scaleFactor = 1.0f / 255.0f; - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[2] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[0] * scaleFactor; - destination[3] = source[3] * scaleFactor; - source += 4; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, float* destination, unsigned pixelsPerRow) -{ - const float scaleFactor = 1.0f / 255.0f; - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[3] * scaleFactor; - destination[1] = source[2] * scaleFactor; - destination[2] = source[1] * scaleFactor; - destination[3] = source[0] * scaleFactor; - source += 4; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, float* destination, unsigned pixelsPerRow) -{ - const float scaleFactor = 1.0f / 255.0f; - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[1] * scaleFactor; - destination[1] = source[2] * scaleFactor; - destination[2] = source[3] * scaleFactor; - destination[3] = source[0] * scaleFactor; - source += 4; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, float* destination, unsigned pixelsPerRow) -{ - const float scaleFactor = 1.0f / 255.0f; - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[2] * scaleFactor; - destination[3] = 1; - source += 3; - destination += 4; - } -} - -template<> void unpack(const uint8_t* source, float* destination, unsigned pixelsPerRow) -{ - const float scaleFactor = 1.0f / 255.0f; - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[2] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[0] * scaleFactor; - destination[3] = 1; - source += 3; - destination += 4; - } -} - -template<> void unpack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[1]; - destination[2] = source[2]; - destination[3] = 1; - source += 3; - destination += 4; - } -} - -template<> void unpack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[0]; - destination[2] = source[0]; - destination[3] = 1; - source += 1; - destination += 4; - } -} - -template<> void unpack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[0]; - destination[2] = source[0]; - destination[3] = source[1]; - source += 2; - destination += 4; - } -} - -template<> void unpack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = 0; - destination[1] = 0; - destination[2] = 0; - destination[3] = source[0]; - source += 1; - destination += 4; - } -} - -//---------------------------------------------------------------------- -// Pixel packing routines. -// - -template -void pack(const SourceType*, DstType*, unsigned) -{ - ASSERT_NOT_REACHED(); -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[3]; - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] / 255.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - destination[0] = sourceR; - source += 4; - destination += 1; - } -} - -// FIXME: this routine is lossy and must be removed. -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - destination[0] = sourceR; - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[3]; - source += 4; - destination += 2; - } -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] / 255.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - destination[0] = sourceR; - destination[1] = source[3]; - source += 4; - destination += 2; - } -} - -// FIXME: this routine is lossy and must be removed. -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - destination[0] = sourceR; - destination[1] = source[3]; - source += 4; - destination += 2; - } -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[1]; - destination[2] = source[2]; - source += 4; - destination += 3; - } -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] / 255.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - destination[0] = sourceR; - destination[1] = sourceG; - destination[2] = sourceB; - source += 4; - destination += 3; - } -} - -// FIXME: this routine is lossy and must be removed. -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - destination[0] = sourceR; - destination[1] = sourceG; - destination[2] = sourceB; - source += 4; - destination += 3; - } -} - - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - memcpy(destination, source, pixelsPerRow * 4); -} - -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] / 255.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - destination[0] = sourceR; - destination[1] = sourceG; - destination[2] = sourceB; - destination[3] = source[3]; - source += 4; - destination += 4; - } -} - -// FIXME: this routine is lossy and must be removed. -template<> void pack(const uint8_t* source, uint8_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - destination[0] = sourceR; - destination[1] = sourceG; - destination[2] = sourceB; - destination[3] = source[3]; - source += 4; - destination += 4; - } -} - -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ -#if HAVE(ARM_NEON_INTRINSICS) - SIMD::packOneRowOfRGBA8ToUnsignedShort4444(source, destination, pixelsPerRow); -#endif - for (unsigned i = 0; i < pixelsPerRow; ++i) { - *destination = (((source[0] & 0xF0) << 8) - | ((source[1] & 0xF0) << 4) - | (source[2] & 0xF0) - | (source[3] >> 4)); - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] / 255.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - *destination = (((sourceR & 0xF0) << 8) - | ((sourceG & 0xF0) << 4) - | (sourceB & 0xF0) - | (source[3] >> 4)); - source += 4; - destination += 1; - } -} - -// FIXME: this routine is lossy and must be removed. -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - *destination = (((sourceR & 0xF0) << 8) - | ((sourceG & 0xF0) << 4) - | (sourceB & 0xF0) - | (source[3] >> 4)); - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ -#if HAVE(ARM_NEON_INTRINSICS) - SIMD::packOneRowOfRGBA8ToUnsignedShort5551(source, destination, pixelsPerRow); -#endif - for (unsigned i = 0; i < pixelsPerRow; ++i) { - *destination = (((source[0] & 0xF8) << 8) - | ((source[1] & 0xF8) << 3) - | ((source[2] & 0xF8) >> 2) - | (source[3] >> 7)); - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] / 255.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - *destination = (((sourceR & 0xF8) << 8) - | ((sourceG & 0xF8) << 3) - | ((sourceB & 0xF8) >> 2) - | (source[3] >> 7)); - source += 4; - destination += 1; - } -} - -// FIXME: this routine is lossy and must be removed. -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - *destination = (((sourceR & 0xF8) << 8) - | ((sourceG & 0xF8) << 3) - | ((sourceB & 0xF8) >> 2) - | (source[3] >> 7)); - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ -#if HAVE(ARM_NEON_INTRINSICS) - SIMD::packOneRowOfRGBA8ToUnsignedShort565(source, destination, pixelsPerRow); -#endif - for (unsigned i = 0; i < pixelsPerRow; ++i) { - *destination = (((source[0] & 0xF8) << 8) - | ((source[1] & 0xFC) << 3) - | ((source[2] & 0xF8) >> 3)); - source += 4; - destination += 1; - } -} - -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] / 255.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - *destination = (((sourceR & 0xF8) << 8) - | ((sourceG & 0xFC) << 3) - | ((sourceB & 0xF8) >> 3)); - source += 4; - destination += 1; - } -} - -// FIXME: this routine is lossy and must be removed. -template<> void pack(const uint8_t* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 255.0f / source[3] : 1.0f; - uint8_t sourceR = static_cast(static_cast(source[0]) * scaleFactor); - uint8_t sourceG = static_cast(static_cast(source[1]) * scaleFactor); - uint8_t sourceB = static_cast(static_cast(source[2]) * scaleFactor); - *destination = (((sourceR & 0xF8) << 8) - | ((sourceG & 0xFC) << 3) - | ((sourceB & 0xF8) >> 3)); - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[1]; - destination[2] = source[2]; - source += 4; - destination += 3; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = source[0] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[2] * scaleFactor; - source += 4; - destination += 3; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = source[0] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[2] * scaleFactor; - source += 4; - destination += 3; - } -} - -// Used only during RGBA8 or BGRA8 -> floating-point uploads. -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - memcpy(destination, source, pixelsPerRow * 4 * sizeof(float)); -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = source[0] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[2] * scaleFactor; - destination[3] = source[3]; - source += 4; - destination += 4; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = source[0] * scaleFactor; - destination[1] = source[1] * scaleFactor; - destination[2] = source[2] * scaleFactor; - destination[3] = source[3]; - source += 4; - destination += 4; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[3]; - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = source[0] * scaleFactor; - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = source[0] * scaleFactor; - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = source[0]; - destination[1] = source[3]; - source += 4; - destination += 2; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = source[0] * scaleFactor; - destination[1] = source[3]; - source += 4; - destination += 2; - } -} - -template<> void pack(const float* source, float* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = source[0] * scaleFactor; - destination[1] = source[3]; - source += 4; - destination += 2; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = convertFloatToHalfFloat(source[0]); - destination[1] = convertFloatToHalfFloat(source[1]); - destination[2] = convertFloatToHalfFloat(source[2]); - destination[3] = convertFloatToHalfFloat(source[3]); - source += 4; - destination += 4; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); - destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); - destination[3] = convertFloatToHalfFloat(source[3]); - source += 4; - destination += 4; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); - destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); - destination[3] = convertFloatToHalfFloat(source[3]); - source += 4; - destination += 4; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = convertFloatToHalfFloat(source[0]); - destination[1] = convertFloatToHalfFloat(source[1]); - destination[2] = convertFloatToHalfFloat(source[2]); - source += 4; - destination += 3; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); - destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); - source += 4; - destination += 3; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - destination[1] = convertFloatToHalfFloat(source[1] * scaleFactor); - destination[2] = convertFloatToHalfFloat(source[2] * scaleFactor); - source += 4; - destination += 3; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = convertFloatToHalfFloat(source[0]); - destination[1] = convertFloatToHalfFloat(source[3]); - source += 4; - destination += 2; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - destination[1] = convertFloatToHalfFloat(source[3]); - source += 4; - destination += 2; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - destination[1] = convertFloatToHalfFloat(source[3]); - source += 4; - destination += 2; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = convertFloatToHalfFloat(source[0]); - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3]; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - float scaleFactor = source[3] ? 1.0f / source[3] : 1.0f; - destination[0] = convertFloatToHalfFloat(source[0] * scaleFactor); - source += 4; - destination += 1; - } -} - -template<> void pack(const float* source, uint16_t* destination, unsigned pixelsPerRow) -{ - for (unsigned i = 0; i < pixelsPerRow; ++i) { - destination[0] = convertFloatToHalfFloat(source[3]); - source += 4; - destination += 1; - } -} - -bool HasAlpha(int format) -{ - return format == WebGLImageConversion::DataFormatA8 - || format == WebGLImageConversion::DataFormatA16F - || format == WebGLImageConversion::DataFormatA32F - || format == WebGLImageConversion::DataFormatRA8 - || format == WebGLImageConversion::DataFormatAR8 - || format == WebGLImageConversion::DataFormatRA16F - || format == WebGLImageConversion::DataFormatRA32F - || format == WebGLImageConversion::DataFormatRGBA8 - || format == WebGLImageConversion::DataFormatBGRA8 - || format == WebGLImageConversion::DataFormatARGB8 - || format == WebGLImageConversion::DataFormatABGR8 - || format == WebGLImageConversion::DataFormatRGBA16F - || format == WebGLImageConversion::DataFormatRGBA32F - || format == WebGLImageConversion::DataFormatRGBA4444 - || format == WebGLImageConversion::DataFormatRGBA5551; -} - -bool HasColor(int format) -{ - return format == WebGLImageConversion::DataFormatRGBA8 - || format == WebGLImageConversion::DataFormatRGBA16F - || format == WebGLImageConversion::DataFormatRGBA32F - || format == WebGLImageConversion::DataFormatRGB8 - || format == WebGLImageConversion::DataFormatRGB16F - || format == WebGLImageConversion::DataFormatRGB32F - || format == WebGLImageConversion::DataFormatBGR8 - || format == WebGLImageConversion::DataFormatBGRA8 - || format == WebGLImageConversion::DataFormatARGB8 - || format == WebGLImageConversion::DataFormatABGR8 - || format == WebGLImageConversion::DataFormatRGBA5551 - || format == WebGLImageConversion::DataFormatRGBA4444 - || format == WebGLImageConversion::DataFormatRGB565 - || format == WebGLImageConversion::DataFormatR8 - || format == WebGLImageConversion::DataFormatR16F - || format == WebGLImageConversion::DataFormatR32F - || format == WebGLImageConversion::DataFormatRA8 - || format == WebGLImageConversion::DataFormatRA16F - || format == WebGLImageConversion::DataFormatRA32F - || format == WebGLImageConversion::DataFormatAR8; -} - -template -struct IsFloatFormat { - static const bool Value = - Format == WebGLImageConversion::DataFormatRGBA32F - || Format == WebGLImageConversion::DataFormatRGB32F - || Format == WebGLImageConversion::DataFormatRA32F - || Format == WebGLImageConversion::DataFormatR32F - || Format == WebGLImageConversion::DataFormatA32F; -}; - -template -struct IsHalfFloatFormat { - static const bool Value = - Format == WebGLImageConversion::DataFormatRGBA16F - || Format == WebGLImageConversion::DataFormatRGB16F - || Format == WebGLImageConversion::DataFormatRA16F - || Format == WebGLImageConversion::DataFormatR16F - || Format == WebGLImageConversion::DataFormatA16F; -}; - -template -struct Is16bppFormat { - static const bool Value = - Format == WebGLImageConversion::DataFormatRGBA5551 - || Format == WebGLImageConversion::DataFormatRGBA4444 - || Format == WebGLImageConversion::DataFormatRGB565; -}; - -template::Value, bool IsHalfFloat = IsHalfFloatFormat::Value, bool Is16bpp = Is16bppFormat::Value> -struct DataTypeForFormat { - typedef uint8_t Type; -}; - -template -struct DataTypeForFormat { - typedef float Type; -}; - -template -struct DataTypeForFormat { - typedef uint16_t Type; -}; - -template -struct DataTypeForFormat { - typedef uint16_t Type; -}; - -template -struct IntermediateFormat { - static const int Value = (IsFloatFormat::Value || IsHalfFloatFormat::Value) ? WebGLImageConversion::DataFormatRGBA32F : WebGLImageConversion::DataFormatRGBA8; -}; - -unsigned TexelBytesForFormat(WebGLImageConversion::DataFormat format) -{ - switch (format) { - case WebGLImageConversion::DataFormatR8: - case WebGLImageConversion::DataFormatA8: - return 1; - case WebGLImageConversion::DataFormatRA8: - case WebGLImageConversion::DataFormatAR8: - case WebGLImageConversion::DataFormatRGBA5551: - case WebGLImageConversion::DataFormatRGBA4444: - case WebGLImageConversion::DataFormatRGB565: - case WebGLImageConversion::DataFormatA16F: - case WebGLImageConversion::DataFormatR16F: - return 2; - case WebGLImageConversion::DataFormatRGB8: - case WebGLImageConversion::DataFormatBGR8: - return 3; - case WebGLImageConversion::DataFormatRGBA8: - case WebGLImageConversion::DataFormatARGB8: - case WebGLImageConversion::DataFormatABGR8: - case WebGLImageConversion::DataFormatBGRA8: - case WebGLImageConversion::DataFormatR32F: - case WebGLImageConversion::DataFormatA32F: - case WebGLImageConversion::DataFormatRA16F: - return 4; - case WebGLImageConversion::DataFormatRGB16F: - return 6; - case WebGLImageConversion::DataFormatRA32F: - case WebGLImageConversion::DataFormatRGBA16F: - return 8; - case WebGLImageConversion::DataFormatRGB32F: - return 12; - case WebGLImageConversion::DataFormatRGBA32F: - return 16; - default: - return 0; - } -} - -/* END CODE SHARED WITH MOZILLA FIREFOX */ - -class FormatConverter { -public: - FormatConverter(unsigned width, unsigned height, - const void* srcStart, void* dstStart, int srcStride, int dstStride) - : m_width(width), m_height(height), m_srcStart(srcStart), m_dstStart(dstStart), m_srcStride(srcStride), m_dstStride(dstStride), m_success(false) - { - const unsigned MaxNumberOfComponents = 4; - const unsigned MaxBytesPerComponent = 4; - m_unpackedIntermediateSrcData = adoptArrayPtr(new uint8_t[m_width * MaxNumberOfComponents *MaxBytesPerComponent]); - ASSERT(m_unpackedIntermediateSrcData.get()); - } - - void convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp); - bool Success() const { return m_success; } - -private: - template - void convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp); - - template - void convert(WebGLImageConversion::AlphaOp); - - template - void convert(); - - const unsigned m_width, m_height; - const void* const m_srcStart; - void* const m_dstStart; - const int m_srcStride, m_dstStride; - bool m_success; - OwnPtr m_unpackedIntermediateSrcData; -}; - -void FormatConverter::convert(WebGLImageConversion::DataFormat srcFormat, WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp) -{ -#define FORMATCONVERTER_CASE_SRCFORMAT(SrcFormat) \ - case SrcFormat: \ - return convert(dstFormat, alphaOp); - - switch (srcFormat) { - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatR32F) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatA32F) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRA32F) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGR8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB565) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGB32F) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatARGB8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatABGR8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatAR8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatBGRA8) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA5551) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA4444) - FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::DataFormatRGBA32F) - default: - ASSERT_NOT_REACHED(); - } -#undef FORMATCONVERTER_CASE_SRCFORMAT -} - -template -void FormatConverter::convert(WebGLImageConversion::DataFormat dstFormat, WebGLImageConversion::AlphaOp alphaOp) -{ -#define FORMATCONVERTER_CASE_DSTFORMAT(DstFormat) \ - case DstFormat: \ - return convert(alphaOp); - - switch (dstFormat) { - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR8) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR16F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatR32F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA8) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA16F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatA32F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA8) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA16F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRA32F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB8) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB565) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB16F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGB32F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA8) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA5551) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA4444) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA16F) - FORMATCONVERTER_CASE_DSTFORMAT(WebGLImageConversion::DataFormatRGBA32F) - default: - ASSERT_NOT_REACHED(); - } - -#undef FORMATCONVERTER_CASE_DSTFORMAT -} - -template -void FormatConverter::convert(WebGLImageConversion::AlphaOp alphaOp) -{ -#define FORMATCONVERTER_CASE_ALPHAOP(alphaOp) \ - case alphaOp: \ - return convert(); - - switch (alphaOp) { - FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoNothing) - FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoPremultiply) - FORMATCONVERTER_CASE_ALPHAOP(WebGLImageConversion::AlphaDoUnmultiply) - default: - ASSERT_NOT_REACHED(); - } -#undef FORMATCONVERTER_CASE_ALPHAOP -} - -template -void FormatConverter::convert() -{ - // Many instantiations of this template function will never be entered, so we try - // to return immediately in these cases to avoid the compiler to generate useless code. - if (SrcFormat == DstFormat && alphaOp == WebGLImageConversion::AlphaDoNothing) { - ASSERT_NOT_REACHED(); - return; - } - if (!IsFloatFormat::Value && IsFloatFormat::Value) { - ASSERT_NOT_REACHED(); - return; - } - - // Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat. - const bool srcFormatComesFromDOMElementOrImageData = WebGLImageConversion::srcFormatComeFromDOMElementOrImageData(SrcFormat); - if (!srcFormatComesFromDOMElementOrImageData && SrcFormat != DstFormat) { - ASSERT_NOT_REACHED(); - return; - } - // Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied. - if (!srcFormatComesFromDOMElementOrImageData && alphaOp == WebGLImageConversion::AlphaDoUnmultiply) { - ASSERT_NOT_REACHED(); - return; - } - if ((!HasAlpha(SrcFormat) || !HasColor(SrcFormat) || !HasColor(DstFormat)) && alphaOp != WebGLImageConversion::AlphaDoNothing) { - ASSERT_NOT_REACHED(); - return; - } - - typedef typename DataTypeForFormat::Type SrcType; - typedef typename DataTypeForFormat::Type DstType; - const int IntermediateSrcFormat = IntermediateFormat::Value; - typedef typename DataTypeForFormat::Type IntermediateSrcType; - const ptrdiff_t srcStrideInElements = m_srcStride / sizeof(SrcType); - const ptrdiff_t dstStrideInElements = m_dstStride / sizeof(DstType); - const bool trivialUnpack = (SrcFormat == WebGLImageConversion::DataFormatRGBA8 && !IsFloatFormat::Value && !IsHalfFloatFormat::Value) || SrcFormat == WebGLImageConversion::DataFormatRGBA32F; - const bool trivialPack = (DstFormat == WebGLImageConversion::DataFormatRGBA8 || DstFormat == WebGLImageConversion::DataFormatRGBA32F) && alphaOp == WebGLImageConversion::AlphaDoNothing && m_dstStride > 0; - ASSERT(!trivialUnpack || !trivialPack); - - const SrcType *srcRowStart = static_cast(m_srcStart); - DstType* dstRowStart = static_cast(m_dstStart); - if (!trivialUnpack && trivialPack) { - for (size_t i = 0; i < m_height; ++i) { - unpack(srcRowStart, dstRowStart, m_width); - srcRowStart += srcStrideInElements; - dstRowStart += dstStrideInElements; - } - } else if (!trivialUnpack && !trivialPack) { - for (size_t i = 0; i < m_height; ++i) { - unpack(srcRowStart, reinterpret_cast(m_unpackedIntermediateSrcData.get()), m_width); - pack(reinterpret_cast(m_unpackedIntermediateSrcData.get()), dstRowStart, m_width); - srcRowStart += srcStrideInElements; - dstRowStart += dstStrideInElements; - } - } else { - for (size_t i = 0; i < m_height; ++i) { - pack(srcRowStart, dstRowStart, m_width); - srcRowStart += srcStrideInElements; - dstRowStart += dstStrideInElements; - } - } - m_success = true; - return; -} - -} // anonymous namespace - -bool WebGLImageConversion::computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent) -{ - switch (format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - *componentsPerPixel = 1; - break; - case GL_LUMINANCE_ALPHA: - *componentsPerPixel = 2; - break; - case GL_RGB: - *componentsPerPixel = 3; - break; - case GL_RGBA: - case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888 - *componentsPerPixel = 4; - break; - default: - return false; - } - switch (type) { - case GL_UNSIGNED_BYTE: - *bytesPerComponent = sizeof(GLubyte); - break; - case GL_UNSIGNED_SHORT: - *bytesPerComponent = sizeof(GLushort); - break; - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - *componentsPerPixel = 1; - *bytesPerComponent = sizeof(GLushort); - break; - case GL_UNSIGNED_INT_24_8_OES: - case GL_UNSIGNED_INT: - *bytesPerComponent = sizeof(GLuint); - break; - case GL_FLOAT: // OES_texture_float - *bytesPerComponent = sizeof(GLfloat); - break; - case GL_HALF_FLOAT_OES: // OES_texture_half_float - *bytesPerComponent = sizeof(GLushort); - break; - default: - return false; - } - return true; -} - -GLenum WebGLImageConversion::computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes) -{ - ASSERT(imageSizeInBytes); - ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8); - if (width < 0 || height < 0) - return GL_INVALID_VALUE; - unsigned bytesPerComponent, componentsPerPixel; - if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel)) - return GL_INVALID_ENUM; - if (!width || !height) { - *imageSizeInBytes = 0; - if (paddingInBytes) - *paddingInBytes = 0; - return GL_NO_ERROR; - } - CheckedInt checkedValue(bytesPerComponent * componentsPerPixel); - checkedValue *= width; - if (!checkedValue.isValid()) - return GL_INVALID_VALUE; - unsigned validRowSize = checkedValue.value(); - unsigned padding = 0; - unsigned residual = validRowSize % alignment; - if (residual) { - padding = alignment - residual; - checkedValue += padding; - } - // Last row needs no padding. - checkedValue *= (height - 1); - checkedValue += validRowSize; - if (!checkedValue.isValid()) - return GL_INVALID_VALUE; - *imageSizeInBytes = checkedValue.value(); - if (paddingInBytes) - *paddingInBytes = padding; - return GL_NO_ERROR; -} - -WebGLImageConversion::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile) -{ - m_image = image; - m_imageHtmlDomSource = imageHtmlDomSource; - m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile); -} - -WebGLImageConversion::ImageExtractor::~ImageExtractor() -{ - if (m_skiaImage) - m_skiaImage->bitmap().unlockPixels(); -} - -bool WebGLImageConversion::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) -{ - if (!m_image) - return false; - m_skiaImage = m_image->nativeImageForCurrentFrame(); - m_alphaOp = AlphaDoNothing; - bool hasAlpha = m_skiaImage ? !m_skiaImage->bitmap().isOpaque() : true; - if ((!m_skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) { - // Attempt to get raw unpremultiplied image data. - OwnPtr decoder(ImageDecoder::create( - *(m_image->data()), ImageSource::AlphaNotPremultiplied, - ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied)); - if (!decoder) - return false; - decoder->setData(m_image->data(), true); - if (!decoder->frameCount()) - return false; - ImageFrame* frame = decoder->frameBufferAtIndex(0); - if (!frame || frame->status() != ImageFrame::FrameComplete) - return false; - hasAlpha = frame->hasAlpha(); - m_nativeImage = frame->asNewNativeImage(); - if (!m_nativeImage.get() || !m_nativeImage->isDataComplete() || !m_nativeImage->bitmap().width() || !m_nativeImage->bitmap().height()) - return false; - if (m_nativeImage->bitmap().colorType() != kN32_SkColorType) - return false; - m_skiaImage = m_nativeImage.get(); - if (hasAlpha && premultiplyAlpha) - m_alphaOp = AlphaDoPremultiply; - } else if (!premultiplyAlpha && hasAlpha) { - // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value for each pixel is 0xFF - // which is true at present and may be changed in the future and needs adjustment accordingly. - // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port, - // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false. - if (m_imageHtmlDomSource != HtmlDomVideo) - m_alphaOp = AlphaDoUnmultiply; - } - if (!m_skiaImage) - return false; - - m_imageSourceFormat = SK_B32_SHIFT ? DataFormatRGBA8 : DataFormatBGRA8; - m_imageWidth = m_skiaImage->bitmap().width(); - m_imageHeight = m_skiaImage->bitmap().height(); - if (!m_imageWidth || !m_imageHeight) { - m_skiaImage.clear(); - return false; - } - // Fail if the image was downsampled because of memory limits. - if (m_imageWidth != (unsigned)m_image->size().width() || m_imageHeight != (unsigned)m_image->size().height()) { - m_skiaImage.clear(); - return false; - } - m_imageSourceUnpackAlignment = 0; - m_skiaImage->bitmap().lockPixels(); - m_imagePixelData = m_skiaImage->bitmap().getPixels(); - return true; -} - -unsigned WebGLImageConversion::getClearBitsByFormat(GLenum format) -{ - switch (format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_RGB: - case GL_RGB565: - case GL_RGBA: - case GL_RGBA4: - case GL_RGB5_A1: - return GL_COLOR_BUFFER_BIT; - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT: - return GL_DEPTH_BUFFER_BIT; - case GL_STENCIL_INDEX8: - return GL_STENCIL_BUFFER_BIT; - case GL_DEPTH_STENCIL_OES: - return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; - default: - return 0; - } -} - -unsigned WebGLImageConversion::getChannelBitsByFormat(GLenum format) -{ - switch (format) { - case GL_ALPHA: - return ChannelAlpha; - case GL_LUMINANCE: - return ChannelRGB; - case GL_LUMINANCE_ALPHA: - return ChannelRGBA; - case GL_RGB: - case GL_RGB565: - return ChannelRGB; - case GL_RGBA: - case GL_RGBA4: - case GL_RGB5_A1: - return ChannelRGBA; - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT: - return ChannelDepth; - case GL_STENCIL_INDEX8: - return ChannelStencil; - case GL_DEPTH_STENCIL_OES: - return ChannelDepth | ChannelStencil; - default: - return 0; - } -} - -bool WebGLImageConversion::packImageData( - Image* image, - const void* pixels, - GLenum format, - GLenum type, - bool flipY, - AlphaOp alphaOp, - DataFormat sourceFormat, - unsigned width, - unsigned height, - unsigned sourceUnpackAlignment, - Vector& data) -{ - if (!pixels) - return false; - - unsigned packedSize; - // Output data is tightly packed (alignment == 1). - if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GL_NO_ERROR) - return false; - data.resize(packedSize); - - if (!packPixels(reinterpret_cast(pixels), sourceFormat, width, height, sourceUnpackAlignment, format, type, alphaOp, data.data(), flipY)) - return false; - if (ImageObserver *observer = image->imageObserver()) - observer->didDraw(image); - return true; -} - -bool WebGLImageConversion::extractImageData( - const uint8_t* imageData, - const IntSize& imageDataSize, - GLenum format, - GLenum type, - bool flipY, - bool premultiplyAlpha, - Vector& data) -{ - if (!imageData) - return false; - int width = imageDataSize.width(); - int height = imageDataSize.height(); - - unsigned packedSize; - // Output data is tightly packed (alignment == 1). - if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, 0) != GL_NO_ERROR) - return false; - data.resize(packedSize); - - if (!packPixels(imageData, DataFormatRGBA8, width, height, 0, format, type, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data(), flipY)) - return false; - - return true; -} - -bool WebGLImageConversion::extractTextureData( - unsigned width, - unsigned height, - GLenum format, GLenum type, - unsigned unpackAlignment, - bool flipY, bool premultiplyAlpha, - const void* pixels, - Vector& data) -{ - // Assumes format, type, etc. have already been validated. - DataFormat sourceDataFormat = getDataFormat(format, type); - - // Resize the output buffer. - unsigned int componentsPerPixel, bytesPerComponent; - if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) - return false; - unsigned bytesPerPixel = componentsPerPixel * bytesPerComponent; - data.resize(width * height * bytesPerPixel); - - if (!packPixels(static_cast(pixels), sourceDataFormat, width, height, unpackAlignment, format, type, (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing), data.data(), flipY)) - return false; - - return true; -} - -bool WebGLImageConversion::packPixels( - const uint8_t* sourceData, - DataFormat sourceDataFormat, - unsigned width, - unsigned height, - unsigned sourceUnpackAlignment, - unsigned destinationFormat, - unsigned destinationType, - AlphaOp alphaOp, - void* destinationData, - bool flipY) -{ - int validSrc = width * TexelBytesForFormat(sourceDataFormat); - int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0; - int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc; - - DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType); - int dstStride = width * TexelBytesForFormat(dstDataFormat); - if (flipY) { - destinationData = static_cast(destinationData) + dstStride*(height - 1); - dstStride = -dstStride; - } - if (!HasAlpha(sourceDataFormat) || !HasColor(sourceDataFormat) || !HasColor(dstDataFormat)) - alphaOp = AlphaDoNothing; - - if (sourceDataFormat == dstDataFormat && alphaOp == AlphaDoNothing) { - const uint8_t* ptr = sourceData; - const uint8_t* ptrEnd = sourceData + srcStride * height; - unsigned rowSize = (dstStride > 0) ? dstStride: -dstStride; - uint8_t* dst = static_cast(destinationData); - while (ptr < ptrEnd) { - memcpy(dst, ptr, rowSize); - ptr += srcStride; - dst += dstStride; - } - return true; - } - - FormatConverter converter(width, height, sourceData, destinationData, srcStride, dstStride); - converter.convert(sourceDataFormat, dstDataFormat, alphaOp); - if (!converter.Success()) - return false; - return true; -} - -} // namespace blink diff --git a/engine/platform/graphics/gpu/WebGLImageConversion.h b/engine/platform/graphics/gpu/WebGLImageConversion.h deleted file mode 100644 index a83d74b8b..000000000 --- a/engine/platform/graphics/gpu/WebGLImageConversion.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SKY_ENGINE_PLATFORM_GRAPHICS_GPU_WEBGLIMAGECONVERSION_H_ -#define SKY_ENGINE_PLATFORM_GRAPHICS_GPU_WEBGLIMAGECONVERSION_H_ - -#include "sky/engine/platform/PlatformExport.h" -#include "sky/engine/platform/graphics/Image.h" -#include "sky/engine/wtf/RefPtr.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" - -namespace blink { -class Image; -class IntSize; - -// Helper functions for texture uploading and pixel readback. -class PLATFORM_EXPORT WebGLImageConversion { -public: - // Attempt to enumerate all possible native image formats to - // reduce the amount of temporary allocations during texture - // uploading. This enum must be public because it is accessed - // by non-member functions. - enum DataFormat { - DataFormatRGBA8 = 0, - DataFormatRGBA16F, - DataFormatRGBA32F, - DataFormatRGB8, - DataFormatRGB16F, - DataFormatRGB32F, - DataFormatBGR8, - DataFormatBGRA8, - DataFormatARGB8, - DataFormatABGR8, - DataFormatRGBA5551, - DataFormatRGBA4444, - DataFormatRGB565, - DataFormatR8, - DataFormatR16F, - DataFormatR32F, - DataFormatRA8, - DataFormatRA16F, - DataFormatRA32F, - DataFormatAR8, - DataFormatA8, - DataFormatA16F, - DataFormatA32F, - DataFormatNumFormats - }; - - enum ChannelBits { - ChannelRed = 1, - ChannelGreen = 2, - ChannelBlue = 4, - ChannelAlpha = 8, - ChannelDepth = 16, - ChannelStencil = 32, - ChannelRGB = ChannelRed | ChannelGreen | ChannelBlue, - ChannelRGBA = ChannelRGB | ChannelAlpha, - }; - - // Possible alpha operations that may need to occur during - // pixel packing. FIXME: kAlphaDoUnmultiply is lossy and must - // be removed. - enum AlphaOp { - AlphaDoNothing = 0, - AlphaDoPremultiply = 1, - AlphaDoUnmultiply = 2 - }; - - enum ImageHtmlDomSource { - HtmlDomImage = 0, - HtmlDomCanvas = 1, - HtmlDomVideo = 2, - HtmlDomNone = 3 - }; - - class PLATFORM_EXPORT ImageExtractor { - public: - ImageExtractor(Image*, ImageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile); - - ~ImageExtractor(); - - bool extractSucceeded() { return m_extractSucceeded; } - const void* imagePixelData() { return m_imagePixelData; } - unsigned imageWidth() { return m_imageWidth; } - unsigned imageHeight() { return m_imageHeight; } - DataFormat imageSourceFormat() { return m_imageSourceFormat; } - AlphaOp imageAlphaOp() { return m_alphaOp; } - unsigned imageSourceUnpackAlignment() { return m_imageSourceUnpackAlignment; } - ImageHtmlDomSource imageHtmlDomSource() { return m_imageHtmlDomSource; } - private: - // Extract the image and keeps track of its status, such as width, height, Source Alignment, format and AlphaOp etc. - // This needs to lock the resources or relevant data if needed and return true upon success - bool extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile); - - RefPtr m_nativeImage; - RefPtr m_skiaImage; - Image* m_image; - ImageHtmlDomSource m_imageHtmlDomSource; - bool m_extractSucceeded; - const void* m_imagePixelData; - unsigned m_imageWidth; - unsigned m_imageHeight; - DataFormat m_imageSourceFormat; - AlphaOp m_alphaOp; - unsigned m_imageSourceUnpackAlignment; - }; - - // Computes the components per pixel and bytes per component - // for the given format and type combination. Returns false if - // either was an invalid enum. - static bool computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent); - - // Computes the image size in bytes. If paddingInBytes is not null, padding - // is also calculated in return. Returns NO_ERROR if succeed, otherwise - // return the suggested GL error indicating the cause of the failure: - // INVALID_VALUE if width/height is negative or overflow happens. - // INVALID_ENUM if format/type is illegal. - static GLenum computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes); - - // Check if the format is one of the formats from the ImageData or DOM elements. - // The formats from ImageData is always RGBA8. - // The formats from DOM elements vary with Graphics ports. It can only be RGBA8 or BGRA8. - static ALWAYS_INLINE bool srcFormatComeFromDOMElementOrImageData(DataFormat SrcFormat) - { - return SrcFormat == DataFormatBGRA8 || SrcFormat == DataFormatRGBA8; - } - - static unsigned getClearBitsByFormat(GLenum); - static unsigned getChannelBitsByFormat(GLenum); - - // The Following functions are implemented in GraphicsContext3DImagePacking.cpp - - // Packs the contents of the given Image which is passed in |pixels| into the passed Vector - // according to the given format and type, and obeying the flipY and AlphaOp flags. - // Returns true upon success. - static bool packImageData(Image*, const void* pixels, GLenum format, GLenum type, bool flipY, AlphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector& data); - - // Extracts the contents of the given ImageData into the passed Vector, - // packing the pixel data according to the given format and type, - // and obeying the flipY and premultiplyAlpha flags. Returns true - // upon success. - static bool extractImageData(const uint8_t*, const IntSize&, GLenum format, GLenum type, bool flipY, bool premultiplyAlpha, Vector& data); - - // Helper function which extracts the user-supplied texture - // data, applying the flipY and premultiplyAlpha parameters. - // If the data is not tightly packed according to the passed - // unpackAlignment, the output data will be tightly packed. - // Returns true if successful, false if any error occurred. - static bool extractTextureData(unsigned width, unsigned height, GLenum format, GLenum type, unsigned unpackAlignment, bool flipY, bool premultiplyAlpha, const void* pixels, Vector& data); - - // End GraphicsContext3DImagePacking.cpp functions - -private: - // Helper for packImageData/extractImageData/extractTextureData which implement packing of pixel - // data into the specified OpenGL destination format and type. - // A sourceUnpackAlignment of zero indicates that the source - // data is tightly packed. Non-zero values may take a slow path. - // Destination data will have no gaps between rows. - // Implemented in GraphicsContext3DImagePacking.cpp - static bool packPixels(const uint8_t* sourceData, DataFormat sourceDataFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, unsigned destinationFormat, unsigned destinationType, AlphaOp, void* destinationData, bool flipY); -}; - -} // namespace blink - -#endif // SKY_ENGINE_PLATFORM_GRAPHICS_GPU_WEBGLIMAGECONVERSION_H_ -- GitLab