diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/graphics/gpu')
14 files changed, 1362 insertions, 131 deletions
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 9017db5231a..e0aeaba9eba 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc @@ -76,6 +76,14 @@ bool g_should_fail_drawing_buffer_creation_for_testing = false; } // namespace +// Increase cache to avoid reallocation on fuchsia, see +// https://crbug.com/1087941. +#if defined(OS_FUCHSIA) +const size_t DrawingBuffer::kDefaultColorBufferCacheLimit = 2; +#else +const size_t DrawingBuffer::kDefaultColorBufferCacheLimit = 1; +#endif + // Function defined in third_party/blink/public/web/blink.h. void ForceNextDrawingBufferCreationToFailForTest() { g_should_fail_drawing_buffer_creation_for_testing = true; @@ -95,6 +103,7 @@ scoped_refptr<DrawingBuffer> DrawingBuffer::Create( PreserveDrawingBuffer preserve, WebGLVersion webgl_version, ChromiumImageUsage chromium_image_usage, + SkFilterQuality filter_quality, const CanvasColorParams& color_params, gl::GpuPreference gpu_preference) { if (g_should_fail_drawing_buffer_creation_for_testing) { @@ -147,7 +156,7 @@ scoped_refptr<DrawingBuffer> DrawingBuffer::Create( std::move(extensions_util), client, discard_framebuffer_supported, want_alpha_channel, premultiplied_alpha, preserve, webgl_version, want_depth_buffer, want_stencil_buffer, chromium_image_usage, - color_params, gpu_preference)); + filter_quality, color_params, gpu_preference)); if (!drawing_buffer->Initialize(size, multisample_supported)) { drawing_buffer->BeginDestruction(); return scoped_refptr<DrawingBuffer>(); @@ -169,6 +178,7 @@ DrawingBuffer::DrawingBuffer( bool want_depth, bool want_stencil, ChromiumImageUsage chromium_image_usage, + SkFilterQuality filter_quality, const CanvasColorParams& color_params, gl::GpuPreference gpu_preference) : client_(client), @@ -189,6 +199,7 @@ DrawingBuffer::DrawingBuffer( sampler_color_space_(color_params.GetSamplerGfxColorSpace()), use_half_float_storage_(color_params.PixelFormat() == CanvasPixelFormat::kF16), + filter_quality_(filter_quality), chromium_image_usage_(chromium_image_usage), opengl_flip_y_extension_( ContextProvider()->GetCapabilities().mesa_framebuffer_flip_y), @@ -338,7 +349,11 @@ bool DrawingBuffer::PrepareTransferableResourceInternal( // 4. Here. return false; } - DCHECK(!is_hidden_); + + // There used to be a DCHECK(!is_hidden_) here, but in some tab + // switching scenarios, it seems that this can racily be called for + // backgrounded tabs. + if (!contents_changed_) return false; @@ -550,7 +565,7 @@ void DrawingBuffer::MailboxReleasedGpu(scoped_refptr<ColorBuffer> color_buffer, // Creation of image backed mailboxes is very expensive, so be less // aggressive about pruning them. Pruning is done in FIFO order. - size_t cache_limit = 1; + size_t cache_limit = kDefaultColorBufferCacheLimit; if (ShouldUseChromiumImage()) cache_limit = 4; while (recycled_color_buffer_queue_.size() >= cache_limit) @@ -1382,6 +1397,7 @@ void DrawingBuffer::RestoreAllState() { client_->DrawingBufferClientRestoreMaskAndClearValues(); client_->DrawingBufferClientRestorePixelPackParameters(); client_->DrawingBufferClientRestoreTexture2DBinding(); + client_->DrawingBufferClientRestoreTextureCubeMapBinding(); client_->DrawingBufferClientRestoreRenderbufferBinding(); client_->DrawingBufferClientRestoreFramebufferBinding(); client_->DrawingBufferClientRestorePixelUnpackBufferBinding(); diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h index 480209908b8..cfbd4502db0 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h @@ -98,6 +98,8 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient, virtual void DrawingBufferClientRestorePixelPackParameters() = 0; // Restores the GL_TEXTURE_2D binding for the active texture unit only. virtual void DrawingBufferClientRestoreTexture2DBinding() = 0; + // Restores the GL_TEXTURE_CUBE_MAP binding for the active texture unit. + virtual void DrawingBufferClientRestoreTextureCubeMapBinding() = 0; virtual void DrawingBufferClientRestoreRenderbufferBinding() = 0; virtual void DrawingBufferClientRestoreFramebufferBinding() = 0; virtual void DrawingBufferClientRestorePixelUnpackBufferBinding() = 0; @@ -136,6 +138,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient, PreserveDrawingBuffer, WebGLVersion, ChromiumImageUsage, + SkFilterQuality, const CanvasColorParams&, gl::GpuPreference); @@ -281,6 +284,8 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient, scoped_refptr<CanvasResource> AsCanvasResource( base::WeakPtr<CanvasResourceProvider> resource_provider); + static const size_t kDefaultColorBufferCacheLimit; + protected: // For unittests DrawingBuffer(std::unique_ptr<WebGraphicsContext3DProvider>, bool using_gpu_compositing, @@ -295,6 +300,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient, bool wants_depth, bool wants_stencil, ChromiumImageUsage, + SkFilterQuality, const CanvasColorParams&, gl::GpuPreference gpu_preference); diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc index 537c1af0001..8509c15a852 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test.cc @@ -246,58 +246,64 @@ TEST_F(DrawingBufferTest, VerifySharedImagesReleasedAfterReleaseCallback) { drawing_buffer_->BeginDestruction(); } -TEST_F(DrawingBufferTest, VerifyOnlyOneRecycledResourceMustBeKept) { - viz::TransferableResource resource1; - std::unique_ptr<viz::SingleReleaseCallback> release_callback1; - viz::TransferableResource resource2; - std::unique_ptr<viz::SingleReleaseCallback> release_callback2; - viz::TransferableResource resource3; - std::unique_ptr<viz::SingleReleaseCallback> release_callback3; +TEST_F(DrawingBufferTest, VerifyCachedRecycledResourcesAreKept) { + const size_t kNumResources = DrawingBuffer::kDefaultColorBufferCacheLimit + 1; + std::vector<viz::TransferableResource> resources(kNumResources); + std::vector<std::unique_ptr<viz::SingleReleaseCallback>> release_callbacks( + kNumResources); // Produce resources. - EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource1, - &release_callback1)); - EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource2, - &release_callback2)); - EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource(nullptr, &resource3, - &release_callback3)); + for (size_t i = 0; i < kNumResources; ++i) { + drawing_buffer_->MarkContentsChanged(); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource( + nullptr, &resources[i], &release_callbacks[i])); + } - // Release resources by specific order; 1, 3, 2. - EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); - release_callback1->Run(gpu::SyncToken(), false /* lostResource */); - EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - release_callback3->Run(gpu::SyncToken(), false /* lostResource */); - EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - release_callback2->Run(gpu::SyncToken(), false /* lostResource */); + // Release resources. + for (auto& release_callback : release_callbacks) { + drawing_buffer_->MarkContentsChanged(); + release_callback->Run(gpu::SyncToken(), false /* lostResource */); + } - // The first recycled resource must be 2. 1 and 3 were deleted by FIFO order - // because DrawingBuffer never keeps more than one resource. - viz::TransferableResource recycled_resource1; - std::unique_ptr<viz::SingleReleaseCallback> recycled_release_callback1; - EXPECT_FALSE(drawing_buffer_->MarkContentsChanged()); - EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource( - nullptr, &recycled_resource1, &recycled_release_callback1)); - EXPECT_EQ(resource2.mailbox_holder.mailbox, - recycled_resource1.mailbox_holder.mailbox); + std::vector<std::unique_ptr<viz::SingleReleaseCallback>> + recycled_release_callbacks(DrawingBuffer::kDefaultColorBufferCacheLimit); + + // The first recycled resource must be from the cache + for (size_t i = 0; i < DrawingBuffer::kDefaultColorBufferCacheLimit; ++i) { + viz::TransferableResource recycled_resource; + std::unique_ptr<viz::SingleReleaseCallback> recycled_release_callback; + drawing_buffer_->MarkContentsChanged(); + EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource( + nullptr, &recycled_resource, &recycled_release_callbacks[i])); + + bool recycled = false; + for (auto& resource : resources) { + if (recycled_resource.mailbox_holder.mailbox == + resource.mailbox_holder.mailbox) { + recycled = true; + break; + } + } + EXPECT_TRUE(recycled); + } - // The second recycled resource must be a new resource. - viz::TransferableResource recycled_resource2; - std::unique_ptr<viz::SingleReleaseCallback> recycled_release_callback2; - EXPECT_TRUE(drawing_buffer_->MarkContentsChanged()); + // The next recycled resource must be a new resource. + viz::TransferableResource next_recycled_resource; + std::unique_ptr<viz::SingleReleaseCallback> next_recycled_release_callback; + drawing_buffer_->MarkContentsChanged(); EXPECT_TRUE(drawing_buffer_->PrepareTransferableResource( - nullptr, &recycled_resource2, &recycled_release_callback2)); - EXPECT_NE(resource1.mailbox_holder.mailbox, - recycled_resource2.mailbox_holder.mailbox); - EXPECT_NE(resource2.mailbox_holder.mailbox, - recycled_resource2.mailbox_holder.mailbox); - EXPECT_NE(resource3.mailbox_holder.mailbox, - recycled_resource2.mailbox_holder.mailbox); - - recycled_release_callback1->Run(gpu::SyncToken(), false /* lostResource */); - recycled_release_callback2->Run(gpu::SyncToken(), false /* lostResource */); + nullptr, &next_recycled_resource, &next_recycled_release_callback)); + for (auto& resource : resources) { + EXPECT_NE(resource.mailbox_holder.mailbox, + next_recycled_resource.mailbox_holder.mailbox); + } + recycled_release_callbacks.push_back( + std::move(next_recycled_release_callback)); + + // Cleanup + for (auto& release_cb : recycled_release_callbacks) { + release_cb->Run(gpu::SyncToken(), false /* lostResource */); + } drawing_buffer_->BeginDestruction(); } @@ -679,7 +685,8 @@ TEST(DrawingBufferDepthStencilTest, packedDepthStencilSupported) { IntSize(10, 10), premultiplied_alpha, want_alpha_channel, want_depth_buffer, want_stencil_buffer, want_antialiasing, preserve, DrawingBuffer::kWebGL1, DrawingBuffer::kAllowChromiumImage, - CanvasColorParams(), gl::GpuPreference::kHighPerformance); + kLow_SkFilterQuality, CanvasColorParams(), + gl::GpuPreference::kHighPerformance); // When we request a depth or a stencil buffer, we will get both. EXPECT_EQ(cases[i].request_depth || cases[i].request_stencil, @@ -749,7 +756,8 @@ TEST_F(DrawingBufferTest, nullptr, gpu_compositing, false /* using_swap_chain */, nullptr, too_big_size, false, false, false, false, false, DrawingBuffer::kDiscard, DrawingBuffer::kWebGL1, DrawingBuffer::kAllowChromiumImage, - CanvasColorParams(), gl::GpuPreference::kHighPerformance); + kLow_SkFilterQuality, CanvasColorParams(), + gl::GpuPreference::kHighPerformance); EXPECT_EQ(too_big_drawing_buffer, nullptr); drawing_buffer_->BeginDestruction(); } diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h index c71278a7b75..f0f8dd37990 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h @@ -92,6 +92,8 @@ class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub, void BindTexture(GLenum target, GLuint texture) override { if (target == GL_TEXTURE_2D) state_.active_texture2d_binding = texture; + if (target == GL_TEXTURE_CUBE_MAP) + state_.active_texturecubemap_binding = texture; bound_textures_.insert(target, texture); } @@ -318,6 +320,10 @@ class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub, void DrawingBufferClientRestoreTexture2DBinding() override { state_.active_texture2d_binding = saved_state_.active_texture2d_binding; } + void DrawingBufferClientRestoreTextureCubeMapBinding() override { + state_.active_texturecubemap_binding = + saved_state_.active_texturecubemap_binding; + } void DrawingBufferClientRestoreRenderbufferBinding() override { state_.renderbuffer_binding = saved_state_.renderbuffer_binding; } @@ -367,6 +373,8 @@ class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub, EXPECT_EQ(state_.pack_alignment, saved_state_.pack_alignment); EXPECT_EQ(state_.active_texture2d_binding, saved_state_.active_texture2d_binding); + EXPECT_EQ(state_.active_texturecubemap_binding, + saved_state_.active_texturecubemap_binding); EXPECT_EQ(state_.renderbuffer_binding, saved_state_.renderbuffer_binding); EXPECT_EQ(state_.draw_framebuffer_binding, saved_state_.draw_framebuffer_binding); @@ -408,6 +416,8 @@ class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub, // The bound 2D texture for the active texture unit. GLuint active_texture2d_binding = 0; + // The bound cube map texture for the active texture unit. + GLuint active_texturecubemap_binding = 0; GLuint renderbuffer_binding = 0; GLuint draw_framebuffer_binding = 0; GLuint read_framebuffer_binding = 0; @@ -471,6 +481,7 @@ class DrawingBufferForTests : public DrawingBuffer { false /* wantDepth */, false /* wantStencil */, DrawingBuffer::kAllowChromiumImage /* ChromiumImageUsage */, + kLow_SkFilterQuality, CanvasColorParams(), gl::GpuPreference::kHighPerformance), live_(nullptr) {} diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc index e8a21596af5..c6afa795ccc 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc @@ -40,7 +40,7 @@ scoped_refptr<StaticBitmapImage> MakeAccelerated( auto provider = CanvasResourceProvider::CreateSharedImageProvider( source->Size(), context_provider_wrapper, kLow_SkFilterQuality, CanvasColorParams(paint_image.GetSkImage()->imageInfo()), - source->IsOriginTopLeft(), CanvasResourceProvider::RasterMode::kGPU, + source->IsOriginTopLeft(), RasterMode::kGPU, gpu::SHARED_IMAGE_USAGE_DISPLAY); if (!provider || !provider->IsAccelerated()) return nullptr; diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h index acfd1b59240..9ca6afb7aa6 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h @@ -57,7 +57,7 @@ class PLATFORM_EXPORT ImageLayerBridge bool IsAccelerated() { return image_ && image_->IsTextureBacked(); } - void Trace(Visitor* visitor) {} + void Trace(Visitor* visitor) const {} private: // SharedMemory bitmap that was registered with SharedBitmapIdRegistrar. Used diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc index 82b5c4a5fd9..468f7b56a0b 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc @@ -168,8 +168,8 @@ TEST_F(SharedGpuContextTest, Canvas2DLayerBridgeAutoRecovery) { IntSize size(10, 10); CanvasColorParams color_params; std::unique_ptr<Canvas2DLayerBridge> bridge = - std::make_unique<Canvas2DLayerBridge>( - size, Canvas2DLayerBridge::kEnableAcceleration, color_params); + std::make_unique<Canvas2DLayerBridge>(size, RasterMode::kGPU, + color_params); EXPECT_TRUE(bridge->IsAccelerated()); EXPECT_TRUE(SharedGpuContext::IsValidWithoutRestoring()); } @@ -195,7 +195,7 @@ TEST_F(BadSharedGpuContextTest, AccelerateImageBufferSurfaceCreationFails) { CanvasResourceProvider::CreateSharedImageProvider( size, SharedGpuContext::ContextProviderWrapper(), kLow_SkFilterQuality, CanvasColorParams(), - true /*is_origin_top_left*/, CanvasResourceProvider::RasterMode::kGPU, + true /*is_origin_top_left*/, RasterMode::kGPU, 0u /*shared_image_usage_flags*/); EXPECT_FALSE(resource_provider); } @@ -222,7 +222,7 @@ TEST_F(SharedGpuContextTestViz, AccelerateImageBufferSurfaceAutoRecovery) { CanvasResourceProvider::CreateSharedImageProvider( size, SharedGpuContext::ContextProviderWrapper(), kLow_SkFilterQuality, CanvasColorParams(), - true /*is_origin_top_left*/, CanvasResourceProvider::RasterMode::kGPU, + true /*is_origin_top_left*/, RasterMode::kGPU, 0u /*shared_image_usage_flags*/); EXPECT_TRUE(resource_provider && resource_provider->IsValid()); EXPECT_TRUE(resource_provider->IsAccelerated()); diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc index 011f6331bfc..25f68839ec3 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc @@ -4,6 +4,7 @@ #include "third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h" +#include <limits> #include <memory> #include "base/compiler_specific.h" @@ -43,6 +44,29 @@ int32_t ClampMin(int32_t value) { return value < kMinInt32Value ? kMinInt32Value : value; } +template <class T> +T ClampImpl(const float& v, const T& lo, const T& hi) { + return (v < lo) ? lo : ((hi < v) ? hi : static_cast<T>(v)); +} + +template <class T> +T ClampFloat(float value) { + if (std::numeric_limits<T>::is_signed) { + // Generate an equal number of positive and negative values. Two's + // complement has one more negative number than positive number. + return ClampImpl<T>(value, std::numeric_limits<T>::min() + 1, + std::numeric_limits<T>::max()); + } else { + return ClampImpl<T>(value, std::numeric_limits<T>::min(), + std::numeric_limits<T>::max()); + } +} + +template <class T> +T ClampAndScaleFloat(float value) { + return ClampFloat<T>(value * std::numeric_limits<T>::max()); +} + // Return kDataFormatNumFormats if format/type combination is invalid. WebGLImageConversion::DataFormat GetDataFormat(GLenum destination_format, GLenum destination_type) { @@ -262,7 +286,7 @@ WebGLImageConversion::DataFormat GetDataFormat(GLenum destination_format, } // The following Float to Half-Float conversion code is from the implementation -// of ftp://www.fox-toolkit.org/pub/fasthalffloatconversion.pdf, "Fast Half +// of http://www.fox-toolkit.org/ftp/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: @@ -309,7 +333,7 @@ void generatetables(){ } */ -uint16_t g_base_table[512] = { +const uint16_t g_base_table[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, @@ -358,7 +382,7 @@ uint16_t g_base_table[512] = { 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512, 64512}; -unsigned char g_shift_table[512] = { +const unsigned char g_shift_table[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, @@ -394,6 +418,421 @@ uint16_t ConvertFloatToHalfFloat(float f) { ((temp & 0x007fffff) >> g_shift_table[signexp]); } +// The mantissatable[2048], offsettable[64] and exponenttable[64] are +// generated as follows: +/* +unsigned int mantissatable[2048]; +unsigned short offsettable[64]; +unsigned int exponenttable[64]; + +unsigned int convertmantissa(unsigned int i) { + unsigned int m=i<<13; // Zero pad mantissa bits + unsigned int e=0; // Zero exponent + while(!(m&0x00800000)){ // While not normalized + e-=0x00800000; // Decrement exponent (1<<23) + m<<=1; // Shift mantissa + } + m&=~0x00800000; // Clear leading 1 bit + e+=0x38800000; // Adjust bias ((127-14)<<23) + return m | e; // Return combined number +} + +void generatef16tof32tables() { + int i; + mantissatable[0] = 0; + for (i = 1; i <= 1023; ++i) + mantissatable[i] = convertmantissa(i); + for (i = 1024; i <= 2047; ++i) + mantissatable[i] = 0x38000000 + ((i-1024)<<13); + + exponenttable[0] = 0; + exponenttable[32]= 0x80000000; + for (int i = 1; i <= 30; ++i) + exponenttable[i] = i<<23; + for (int i = 33; i <= 62; ++i) + exponenttable[i] = 0x80000000 + ((i-32)<<23); + exponenttable[31]= 0x47800000; + exponenttable[63]= 0xC7800000; + + for (i = 0; i <= 63; ++i) + offsettable[i] = 1024; + offsettable[0] = 0; + offsettable[32] = 0; +} +*/ + +const uint32_t g_mantissa_table[2048] = { + 0x0, 0x33800000, 0x34000000, 0x34400000, 0x34800000, 0x34a00000, + 0x34c00000, 0x34e00000, 0x35000000, 0x35100000, 0x35200000, 0x35300000, + 0x35400000, 0x35500000, 0x35600000, 0x35700000, 0x35800000, 0x35880000, + 0x35900000, 0x35980000, 0x35a00000, 0x35a80000, 0x35b00000, 0x35b80000, + 0x35c00000, 0x35c80000, 0x35d00000, 0x35d80000, 0x35e00000, 0x35e80000, + 0x35f00000, 0x35f80000, 0x36000000, 0x36040000, 0x36080000, 0x360c0000, + 0x36100000, 0x36140000, 0x36180000, 0x361c0000, 0x36200000, 0x36240000, + 0x36280000, 0x362c0000, 0x36300000, 0x36340000, 0x36380000, 0x363c0000, + 0x36400000, 0x36440000, 0x36480000, 0x364c0000, 0x36500000, 0x36540000, + 0x36580000, 0x365c0000, 0x36600000, 0x36640000, 0x36680000, 0x366c0000, + 0x36700000, 0x36740000, 0x36780000, 0x367c0000, 0x36800000, 0x36820000, + 0x36840000, 0x36860000, 0x36880000, 0x368a0000, 0x368c0000, 0x368e0000, + 0x36900000, 0x36920000, 0x36940000, 0x36960000, 0x36980000, 0x369a0000, + 0x369c0000, 0x369e0000, 0x36a00000, 0x36a20000, 0x36a40000, 0x36a60000, + 0x36a80000, 0x36aa0000, 0x36ac0000, 0x36ae0000, 0x36b00000, 0x36b20000, + 0x36b40000, 0x36b60000, 0x36b80000, 0x36ba0000, 0x36bc0000, 0x36be0000, + 0x36c00000, 0x36c20000, 0x36c40000, 0x36c60000, 0x36c80000, 0x36ca0000, + 0x36cc0000, 0x36ce0000, 0x36d00000, 0x36d20000, 0x36d40000, 0x36d60000, + 0x36d80000, 0x36da0000, 0x36dc0000, 0x36de0000, 0x36e00000, 0x36e20000, + 0x36e40000, 0x36e60000, 0x36e80000, 0x36ea0000, 0x36ec0000, 0x36ee0000, + 0x36f00000, 0x36f20000, 0x36f40000, 0x36f60000, 0x36f80000, 0x36fa0000, + 0x36fc0000, 0x36fe0000, 0x37000000, 0x37010000, 0x37020000, 0x37030000, + 0x37040000, 0x37050000, 0x37060000, 0x37070000, 0x37080000, 0x37090000, + 0x370a0000, 0x370b0000, 0x370c0000, 0x370d0000, 0x370e0000, 0x370f0000, + 0x37100000, 0x37110000, 0x37120000, 0x37130000, 0x37140000, 0x37150000, + 0x37160000, 0x37170000, 0x37180000, 0x37190000, 0x371a0000, 0x371b0000, + 0x371c0000, 0x371d0000, 0x371e0000, 0x371f0000, 0x37200000, 0x37210000, + 0x37220000, 0x37230000, 0x37240000, 0x37250000, 0x37260000, 0x37270000, + 0x37280000, 0x37290000, 0x372a0000, 0x372b0000, 0x372c0000, 0x372d0000, + 0x372e0000, 0x372f0000, 0x37300000, 0x37310000, 0x37320000, 0x37330000, + 0x37340000, 0x37350000, 0x37360000, 0x37370000, 0x37380000, 0x37390000, + 0x373a0000, 0x373b0000, 0x373c0000, 0x373d0000, 0x373e0000, 0x373f0000, + 0x37400000, 0x37410000, 0x37420000, 0x37430000, 0x37440000, 0x37450000, + 0x37460000, 0x37470000, 0x37480000, 0x37490000, 0x374a0000, 0x374b0000, + 0x374c0000, 0x374d0000, 0x374e0000, 0x374f0000, 0x37500000, 0x37510000, + 0x37520000, 0x37530000, 0x37540000, 0x37550000, 0x37560000, 0x37570000, + 0x37580000, 0x37590000, 0x375a0000, 0x375b0000, 0x375c0000, 0x375d0000, + 0x375e0000, 0x375f0000, 0x37600000, 0x37610000, 0x37620000, 0x37630000, + 0x37640000, 0x37650000, 0x37660000, 0x37670000, 0x37680000, 0x37690000, + 0x376a0000, 0x376b0000, 0x376c0000, 0x376d0000, 0x376e0000, 0x376f0000, + 0x37700000, 0x37710000, 0x37720000, 0x37730000, 0x37740000, 0x37750000, + 0x37760000, 0x37770000, 0x37780000, 0x37790000, 0x377a0000, 0x377b0000, + 0x377c0000, 0x377d0000, 0x377e0000, 0x377f0000, 0x37800000, 0x37808000, + 0x37810000, 0x37818000, 0x37820000, 0x37828000, 0x37830000, 0x37838000, + 0x37840000, 0x37848000, 0x37850000, 0x37858000, 0x37860000, 0x37868000, + 0x37870000, 0x37878000, 0x37880000, 0x37888000, 0x37890000, 0x37898000, + 0x378a0000, 0x378a8000, 0x378b0000, 0x378b8000, 0x378c0000, 0x378c8000, + 0x378d0000, 0x378d8000, 0x378e0000, 0x378e8000, 0x378f0000, 0x378f8000, + 0x37900000, 0x37908000, 0x37910000, 0x37918000, 0x37920000, 0x37928000, + 0x37930000, 0x37938000, 0x37940000, 0x37948000, 0x37950000, 0x37958000, + 0x37960000, 0x37968000, 0x37970000, 0x37978000, 0x37980000, 0x37988000, + 0x37990000, 0x37998000, 0x379a0000, 0x379a8000, 0x379b0000, 0x379b8000, + 0x379c0000, 0x379c8000, 0x379d0000, 0x379d8000, 0x379e0000, 0x379e8000, + 0x379f0000, 0x379f8000, 0x37a00000, 0x37a08000, 0x37a10000, 0x37a18000, + 0x37a20000, 0x37a28000, 0x37a30000, 0x37a38000, 0x37a40000, 0x37a48000, + 0x37a50000, 0x37a58000, 0x37a60000, 0x37a68000, 0x37a70000, 0x37a78000, + 0x37a80000, 0x37a88000, 0x37a90000, 0x37a98000, 0x37aa0000, 0x37aa8000, + 0x37ab0000, 0x37ab8000, 0x37ac0000, 0x37ac8000, 0x37ad0000, 0x37ad8000, + 0x37ae0000, 0x37ae8000, 0x37af0000, 0x37af8000, 0x37b00000, 0x37b08000, + 0x37b10000, 0x37b18000, 0x37b20000, 0x37b28000, 0x37b30000, 0x37b38000, + 0x37b40000, 0x37b48000, 0x37b50000, 0x37b58000, 0x37b60000, 0x37b68000, + 0x37b70000, 0x37b78000, 0x37b80000, 0x37b88000, 0x37b90000, 0x37b98000, + 0x37ba0000, 0x37ba8000, 0x37bb0000, 0x37bb8000, 0x37bc0000, 0x37bc8000, + 0x37bd0000, 0x37bd8000, 0x37be0000, 0x37be8000, 0x37bf0000, 0x37bf8000, + 0x37c00000, 0x37c08000, 0x37c10000, 0x37c18000, 0x37c20000, 0x37c28000, + 0x37c30000, 0x37c38000, 0x37c40000, 0x37c48000, 0x37c50000, 0x37c58000, + 0x37c60000, 0x37c68000, 0x37c70000, 0x37c78000, 0x37c80000, 0x37c88000, + 0x37c90000, 0x37c98000, 0x37ca0000, 0x37ca8000, 0x37cb0000, 0x37cb8000, + 0x37cc0000, 0x37cc8000, 0x37cd0000, 0x37cd8000, 0x37ce0000, 0x37ce8000, + 0x37cf0000, 0x37cf8000, 0x37d00000, 0x37d08000, 0x37d10000, 0x37d18000, + 0x37d20000, 0x37d28000, 0x37d30000, 0x37d38000, 0x37d40000, 0x37d48000, + 0x37d50000, 0x37d58000, 0x37d60000, 0x37d68000, 0x37d70000, 0x37d78000, + 0x37d80000, 0x37d88000, 0x37d90000, 0x37d98000, 0x37da0000, 0x37da8000, + 0x37db0000, 0x37db8000, 0x37dc0000, 0x37dc8000, 0x37dd0000, 0x37dd8000, + 0x37de0000, 0x37de8000, 0x37df0000, 0x37df8000, 0x37e00000, 0x37e08000, + 0x37e10000, 0x37e18000, 0x37e20000, 0x37e28000, 0x37e30000, 0x37e38000, + 0x37e40000, 0x37e48000, 0x37e50000, 0x37e58000, 0x37e60000, 0x37e68000, + 0x37e70000, 0x37e78000, 0x37e80000, 0x37e88000, 0x37e90000, 0x37e98000, + 0x37ea0000, 0x37ea8000, 0x37eb0000, 0x37eb8000, 0x37ec0000, 0x37ec8000, + 0x37ed0000, 0x37ed8000, 0x37ee0000, 0x37ee8000, 0x37ef0000, 0x37ef8000, + 0x37f00000, 0x37f08000, 0x37f10000, 0x37f18000, 0x37f20000, 0x37f28000, + 0x37f30000, 0x37f38000, 0x37f40000, 0x37f48000, 0x37f50000, 0x37f58000, + 0x37f60000, 0x37f68000, 0x37f70000, 0x37f78000, 0x37f80000, 0x37f88000, + 0x37f90000, 0x37f98000, 0x37fa0000, 0x37fa8000, 0x37fb0000, 0x37fb8000, + 0x37fc0000, 0x37fc8000, 0x37fd0000, 0x37fd8000, 0x37fe0000, 0x37fe8000, + 0x37ff0000, 0x37ff8000, 0x38000000, 0x38004000, 0x38008000, 0x3800c000, + 0x38010000, 0x38014000, 0x38018000, 0x3801c000, 0x38020000, 0x38024000, + 0x38028000, 0x3802c000, 0x38030000, 0x38034000, 0x38038000, 0x3803c000, + 0x38040000, 0x38044000, 0x38048000, 0x3804c000, 0x38050000, 0x38054000, + 0x38058000, 0x3805c000, 0x38060000, 0x38064000, 0x38068000, 0x3806c000, + 0x38070000, 0x38074000, 0x38078000, 0x3807c000, 0x38080000, 0x38084000, + 0x38088000, 0x3808c000, 0x38090000, 0x38094000, 0x38098000, 0x3809c000, + 0x380a0000, 0x380a4000, 0x380a8000, 0x380ac000, 0x380b0000, 0x380b4000, + 0x380b8000, 0x380bc000, 0x380c0000, 0x380c4000, 0x380c8000, 0x380cc000, + 0x380d0000, 0x380d4000, 0x380d8000, 0x380dc000, 0x380e0000, 0x380e4000, + 0x380e8000, 0x380ec000, 0x380f0000, 0x380f4000, 0x380f8000, 0x380fc000, + 0x38100000, 0x38104000, 0x38108000, 0x3810c000, 0x38110000, 0x38114000, + 0x38118000, 0x3811c000, 0x38120000, 0x38124000, 0x38128000, 0x3812c000, + 0x38130000, 0x38134000, 0x38138000, 0x3813c000, 0x38140000, 0x38144000, + 0x38148000, 0x3814c000, 0x38150000, 0x38154000, 0x38158000, 0x3815c000, + 0x38160000, 0x38164000, 0x38168000, 0x3816c000, 0x38170000, 0x38174000, + 0x38178000, 0x3817c000, 0x38180000, 0x38184000, 0x38188000, 0x3818c000, + 0x38190000, 0x38194000, 0x38198000, 0x3819c000, 0x381a0000, 0x381a4000, + 0x381a8000, 0x381ac000, 0x381b0000, 0x381b4000, 0x381b8000, 0x381bc000, + 0x381c0000, 0x381c4000, 0x381c8000, 0x381cc000, 0x381d0000, 0x381d4000, + 0x381d8000, 0x381dc000, 0x381e0000, 0x381e4000, 0x381e8000, 0x381ec000, + 0x381f0000, 0x381f4000, 0x381f8000, 0x381fc000, 0x38200000, 0x38204000, + 0x38208000, 0x3820c000, 0x38210000, 0x38214000, 0x38218000, 0x3821c000, + 0x38220000, 0x38224000, 0x38228000, 0x3822c000, 0x38230000, 0x38234000, + 0x38238000, 0x3823c000, 0x38240000, 0x38244000, 0x38248000, 0x3824c000, + 0x38250000, 0x38254000, 0x38258000, 0x3825c000, 0x38260000, 0x38264000, + 0x38268000, 0x3826c000, 0x38270000, 0x38274000, 0x38278000, 0x3827c000, + 0x38280000, 0x38284000, 0x38288000, 0x3828c000, 0x38290000, 0x38294000, + 0x38298000, 0x3829c000, 0x382a0000, 0x382a4000, 0x382a8000, 0x382ac000, + 0x382b0000, 0x382b4000, 0x382b8000, 0x382bc000, 0x382c0000, 0x382c4000, + 0x382c8000, 0x382cc000, 0x382d0000, 0x382d4000, 0x382d8000, 0x382dc000, + 0x382e0000, 0x382e4000, 0x382e8000, 0x382ec000, 0x382f0000, 0x382f4000, + 0x382f8000, 0x382fc000, 0x38300000, 0x38304000, 0x38308000, 0x3830c000, + 0x38310000, 0x38314000, 0x38318000, 0x3831c000, 0x38320000, 0x38324000, + 0x38328000, 0x3832c000, 0x38330000, 0x38334000, 0x38338000, 0x3833c000, + 0x38340000, 0x38344000, 0x38348000, 0x3834c000, 0x38350000, 0x38354000, + 0x38358000, 0x3835c000, 0x38360000, 0x38364000, 0x38368000, 0x3836c000, + 0x38370000, 0x38374000, 0x38378000, 0x3837c000, 0x38380000, 0x38384000, + 0x38388000, 0x3838c000, 0x38390000, 0x38394000, 0x38398000, 0x3839c000, + 0x383a0000, 0x383a4000, 0x383a8000, 0x383ac000, 0x383b0000, 0x383b4000, + 0x383b8000, 0x383bc000, 0x383c0000, 0x383c4000, 0x383c8000, 0x383cc000, + 0x383d0000, 0x383d4000, 0x383d8000, 0x383dc000, 0x383e0000, 0x383e4000, + 0x383e8000, 0x383ec000, 0x383f0000, 0x383f4000, 0x383f8000, 0x383fc000, + 0x38400000, 0x38404000, 0x38408000, 0x3840c000, 0x38410000, 0x38414000, + 0x38418000, 0x3841c000, 0x38420000, 0x38424000, 0x38428000, 0x3842c000, + 0x38430000, 0x38434000, 0x38438000, 0x3843c000, 0x38440000, 0x38444000, + 0x38448000, 0x3844c000, 0x38450000, 0x38454000, 0x38458000, 0x3845c000, + 0x38460000, 0x38464000, 0x38468000, 0x3846c000, 0x38470000, 0x38474000, + 0x38478000, 0x3847c000, 0x38480000, 0x38484000, 0x38488000, 0x3848c000, + 0x38490000, 0x38494000, 0x38498000, 0x3849c000, 0x384a0000, 0x384a4000, + 0x384a8000, 0x384ac000, 0x384b0000, 0x384b4000, 0x384b8000, 0x384bc000, + 0x384c0000, 0x384c4000, 0x384c8000, 0x384cc000, 0x384d0000, 0x384d4000, + 0x384d8000, 0x384dc000, 0x384e0000, 0x384e4000, 0x384e8000, 0x384ec000, + 0x384f0000, 0x384f4000, 0x384f8000, 0x384fc000, 0x38500000, 0x38504000, + 0x38508000, 0x3850c000, 0x38510000, 0x38514000, 0x38518000, 0x3851c000, + 0x38520000, 0x38524000, 0x38528000, 0x3852c000, 0x38530000, 0x38534000, + 0x38538000, 0x3853c000, 0x38540000, 0x38544000, 0x38548000, 0x3854c000, + 0x38550000, 0x38554000, 0x38558000, 0x3855c000, 0x38560000, 0x38564000, + 0x38568000, 0x3856c000, 0x38570000, 0x38574000, 0x38578000, 0x3857c000, + 0x38580000, 0x38584000, 0x38588000, 0x3858c000, 0x38590000, 0x38594000, + 0x38598000, 0x3859c000, 0x385a0000, 0x385a4000, 0x385a8000, 0x385ac000, + 0x385b0000, 0x385b4000, 0x385b8000, 0x385bc000, 0x385c0000, 0x385c4000, + 0x385c8000, 0x385cc000, 0x385d0000, 0x385d4000, 0x385d8000, 0x385dc000, + 0x385e0000, 0x385e4000, 0x385e8000, 0x385ec000, 0x385f0000, 0x385f4000, + 0x385f8000, 0x385fc000, 0x38600000, 0x38604000, 0x38608000, 0x3860c000, + 0x38610000, 0x38614000, 0x38618000, 0x3861c000, 0x38620000, 0x38624000, + 0x38628000, 0x3862c000, 0x38630000, 0x38634000, 0x38638000, 0x3863c000, + 0x38640000, 0x38644000, 0x38648000, 0x3864c000, 0x38650000, 0x38654000, + 0x38658000, 0x3865c000, 0x38660000, 0x38664000, 0x38668000, 0x3866c000, + 0x38670000, 0x38674000, 0x38678000, 0x3867c000, 0x38680000, 0x38684000, + 0x38688000, 0x3868c000, 0x38690000, 0x38694000, 0x38698000, 0x3869c000, + 0x386a0000, 0x386a4000, 0x386a8000, 0x386ac000, 0x386b0000, 0x386b4000, + 0x386b8000, 0x386bc000, 0x386c0000, 0x386c4000, 0x386c8000, 0x386cc000, + 0x386d0000, 0x386d4000, 0x386d8000, 0x386dc000, 0x386e0000, 0x386e4000, + 0x386e8000, 0x386ec000, 0x386f0000, 0x386f4000, 0x386f8000, 0x386fc000, + 0x38700000, 0x38704000, 0x38708000, 0x3870c000, 0x38710000, 0x38714000, + 0x38718000, 0x3871c000, 0x38720000, 0x38724000, 0x38728000, 0x3872c000, + 0x38730000, 0x38734000, 0x38738000, 0x3873c000, 0x38740000, 0x38744000, + 0x38748000, 0x3874c000, 0x38750000, 0x38754000, 0x38758000, 0x3875c000, + 0x38760000, 0x38764000, 0x38768000, 0x3876c000, 0x38770000, 0x38774000, + 0x38778000, 0x3877c000, 0x38780000, 0x38784000, 0x38788000, 0x3878c000, + 0x38790000, 0x38794000, 0x38798000, 0x3879c000, 0x387a0000, 0x387a4000, + 0x387a8000, 0x387ac000, 0x387b0000, 0x387b4000, 0x387b8000, 0x387bc000, + 0x387c0000, 0x387c4000, 0x387c8000, 0x387cc000, 0x387d0000, 0x387d4000, + 0x387d8000, 0x387dc000, 0x387e0000, 0x387e4000, 0x387e8000, 0x387ec000, + 0x387f0000, 0x387f4000, 0x387f8000, 0x387fc000, 0x38000000, 0x38002000, + 0x38004000, 0x38006000, 0x38008000, 0x3800a000, 0x3800c000, 0x3800e000, + 0x38010000, 0x38012000, 0x38014000, 0x38016000, 0x38018000, 0x3801a000, + 0x3801c000, 0x3801e000, 0x38020000, 0x38022000, 0x38024000, 0x38026000, + 0x38028000, 0x3802a000, 0x3802c000, 0x3802e000, 0x38030000, 0x38032000, + 0x38034000, 0x38036000, 0x38038000, 0x3803a000, 0x3803c000, 0x3803e000, + 0x38040000, 0x38042000, 0x38044000, 0x38046000, 0x38048000, 0x3804a000, + 0x3804c000, 0x3804e000, 0x38050000, 0x38052000, 0x38054000, 0x38056000, + 0x38058000, 0x3805a000, 0x3805c000, 0x3805e000, 0x38060000, 0x38062000, + 0x38064000, 0x38066000, 0x38068000, 0x3806a000, 0x3806c000, 0x3806e000, + 0x38070000, 0x38072000, 0x38074000, 0x38076000, 0x38078000, 0x3807a000, + 0x3807c000, 0x3807e000, 0x38080000, 0x38082000, 0x38084000, 0x38086000, + 0x38088000, 0x3808a000, 0x3808c000, 0x3808e000, 0x38090000, 0x38092000, + 0x38094000, 0x38096000, 0x38098000, 0x3809a000, 0x3809c000, 0x3809e000, + 0x380a0000, 0x380a2000, 0x380a4000, 0x380a6000, 0x380a8000, 0x380aa000, + 0x380ac000, 0x380ae000, 0x380b0000, 0x380b2000, 0x380b4000, 0x380b6000, + 0x380b8000, 0x380ba000, 0x380bc000, 0x380be000, 0x380c0000, 0x380c2000, + 0x380c4000, 0x380c6000, 0x380c8000, 0x380ca000, 0x380cc000, 0x380ce000, + 0x380d0000, 0x380d2000, 0x380d4000, 0x380d6000, 0x380d8000, 0x380da000, + 0x380dc000, 0x380de000, 0x380e0000, 0x380e2000, 0x380e4000, 0x380e6000, + 0x380e8000, 0x380ea000, 0x380ec000, 0x380ee000, 0x380f0000, 0x380f2000, + 0x380f4000, 0x380f6000, 0x380f8000, 0x380fa000, 0x380fc000, 0x380fe000, + 0x38100000, 0x38102000, 0x38104000, 0x38106000, 0x38108000, 0x3810a000, + 0x3810c000, 0x3810e000, 0x38110000, 0x38112000, 0x38114000, 0x38116000, + 0x38118000, 0x3811a000, 0x3811c000, 0x3811e000, 0x38120000, 0x38122000, + 0x38124000, 0x38126000, 0x38128000, 0x3812a000, 0x3812c000, 0x3812e000, + 0x38130000, 0x38132000, 0x38134000, 0x38136000, 0x38138000, 0x3813a000, + 0x3813c000, 0x3813e000, 0x38140000, 0x38142000, 0x38144000, 0x38146000, + 0x38148000, 0x3814a000, 0x3814c000, 0x3814e000, 0x38150000, 0x38152000, + 0x38154000, 0x38156000, 0x38158000, 0x3815a000, 0x3815c000, 0x3815e000, + 0x38160000, 0x38162000, 0x38164000, 0x38166000, 0x38168000, 0x3816a000, + 0x3816c000, 0x3816e000, 0x38170000, 0x38172000, 0x38174000, 0x38176000, + 0x38178000, 0x3817a000, 0x3817c000, 0x3817e000, 0x38180000, 0x38182000, + 0x38184000, 0x38186000, 0x38188000, 0x3818a000, 0x3818c000, 0x3818e000, + 0x38190000, 0x38192000, 0x38194000, 0x38196000, 0x38198000, 0x3819a000, + 0x3819c000, 0x3819e000, 0x381a0000, 0x381a2000, 0x381a4000, 0x381a6000, + 0x381a8000, 0x381aa000, 0x381ac000, 0x381ae000, 0x381b0000, 0x381b2000, + 0x381b4000, 0x381b6000, 0x381b8000, 0x381ba000, 0x381bc000, 0x381be000, + 0x381c0000, 0x381c2000, 0x381c4000, 0x381c6000, 0x381c8000, 0x381ca000, + 0x381cc000, 0x381ce000, 0x381d0000, 0x381d2000, 0x381d4000, 0x381d6000, + 0x381d8000, 0x381da000, 0x381dc000, 0x381de000, 0x381e0000, 0x381e2000, + 0x381e4000, 0x381e6000, 0x381e8000, 0x381ea000, 0x381ec000, 0x381ee000, + 0x381f0000, 0x381f2000, 0x381f4000, 0x381f6000, 0x381f8000, 0x381fa000, + 0x381fc000, 0x381fe000, 0x38200000, 0x38202000, 0x38204000, 0x38206000, + 0x38208000, 0x3820a000, 0x3820c000, 0x3820e000, 0x38210000, 0x38212000, + 0x38214000, 0x38216000, 0x38218000, 0x3821a000, 0x3821c000, 0x3821e000, + 0x38220000, 0x38222000, 0x38224000, 0x38226000, 0x38228000, 0x3822a000, + 0x3822c000, 0x3822e000, 0x38230000, 0x38232000, 0x38234000, 0x38236000, + 0x38238000, 0x3823a000, 0x3823c000, 0x3823e000, 0x38240000, 0x38242000, + 0x38244000, 0x38246000, 0x38248000, 0x3824a000, 0x3824c000, 0x3824e000, + 0x38250000, 0x38252000, 0x38254000, 0x38256000, 0x38258000, 0x3825a000, + 0x3825c000, 0x3825e000, 0x38260000, 0x38262000, 0x38264000, 0x38266000, + 0x38268000, 0x3826a000, 0x3826c000, 0x3826e000, 0x38270000, 0x38272000, + 0x38274000, 0x38276000, 0x38278000, 0x3827a000, 0x3827c000, 0x3827e000, + 0x38280000, 0x38282000, 0x38284000, 0x38286000, 0x38288000, 0x3828a000, + 0x3828c000, 0x3828e000, 0x38290000, 0x38292000, 0x38294000, 0x38296000, + 0x38298000, 0x3829a000, 0x3829c000, 0x3829e000, 0x382a0000, 0x382a2000, + 0x382a4000, 0x382a6000, 0x382a8000, 0x382aa000, 0x382ac000, 0x382ae000, + 0x382b0000, 0x382b2000, 0x382b4000, 0x382b6000, 0x382b8000, 0x382ba000, + 0x382bc000, 0x382be000, 0x382c0000, 0x382c2000, 0x382c4000, 0x382c6000, + 0x382c8000, 0x382ca000, 0x382cc000, 0x382ce000, 0x382d0000, 0x382d2000, + 0x382d4000, 0x382d6000, 0x382d8000, 0x382da000, 0x382dc000, 0x382de000, + 0x382e0000, 0x382e2000, 0x382e4000, 0x382e6000, 0x382e8000, 0x382ea000, + 0x382ec000, 0x382ee000, 0x382f0000, 0x382f2000, 0x382f4000, 0x382f6000, + 0x382f8000, 0x382fa000, 0x382fc000, 0x382fe000, 0x38300000, 0x38302000, + 0x38304000, 0x38306000, 0x38308000, 0x3830a000, 0x3830c000, 0x3830e000, + 0x38310000, 0x38312000, 0x38314000, 0x38316000, 0x38318000, 0x3831a000, + 0x3831c000, 0x3831e000, 0x38320000, 0x38322000, 0x38324000, 0x38326000, + 0x38328000, 0x3832a000, 0x3832c000, 0x3832e000, 0x38330000, 0x38332000, + 0x38334000, 0x38336000, 0x38338000, 0x3833a000, 0x3833c000, 0x3833e000, + 0x38340000, 0x38342000, 0x38344000, 0x38346000, 0x38348000, 0x3834a000, + 0x3834c000, 0x3834e000, 0x38350000, 0x38352000, 0x38354000, 0x38356000, + 0x38358000, 0x3835a000, 0x3835c000, 0x3835e000, 0x38360000, 0x38362000, + 0x38364000, 0x38366000, 0x38368000, 0x3836a000, 0x3836c000, 0x3836e000, + 0x38370000, 0x38372000, 0x38374000, 0x38376000, 0x38378000, 0x3837a000, + 0x3837c000, 0x3837e000, 0x38380000, 0x38382000, 0x38384000, 0x38386000, + 0x38388000, 0x3838a000, 0x3838c000, 0x3838e000, 0x38390000, 0x38392000, + 0x38394000, 0x38396000, 0x38398000, 0x3839a000, 0x3839c000, 0x3839e000, + 0x383a0000, 0x383a2000, 0x383a4000, 0x383a6000, 0x383a8000, 0x383aa000, + 0x383ac000, 0x383ae000, 0x383b0000, 0x383b2000, 0x383b4000, 0x383b6000, + 0x383b8000, 0x383ba000, 0x383bc000, 0x383be000, 0x383c0000, 0x383c2000, + 0x383c4000, 0x383c6000, 0x383c8000, 0x383ca000, 0x383cc000, 0x383ce000, + 0x383d0000, 0x383d2000, 0x383d4000, 0x383d6000, 0x383d8000, 0x383da000, + 0x383dc000, 0x383de000, 0x383e0000, 0x383e2000, 0x383e4000, 0x383e6000, + 0x383e8000, 0x383ea000, 0x383ec000, 0x383ee000, 0x383f0000, 0x383f2000, + 0x383f4000, 0x383f6000, 0x383f8000, 0x383fa000, 0x383fc000, 0x383fe000, + 0x38400000, 0x38402000, 0x38404000, 0x38406000, 0x38408000, 0x3840a000, + 0x3840c000, 0x3840e000, 0x38410000, 0x38412000, 0x38414000, 0x38416000, + 0x38418000, 0x3841a000, 0x3841c000, 0x3841e000, 0x38420000, 0x38422000, + 0x38424000, 0x38426000, 0x38428000, 0x3842a000, 0x3842c000, 0x3842e000, + 0x38430000, 0x38432000, 0x38434000, 0x38436000, 0x38438000, 0x3843a000, + 0x3843c000, 0x3843e000, 0x38440000, 0x38442000, 0x38444000, 0x38446000, + 0x38448000, 0x3844a000, 0x3844c000, 0x3844e000, 0x38450000, 0x38452000, + 0x38454000, 0x38456000, 0x38458000, 0x3845a000, 0x3845c000, 0x3845e000, + 0x38460000, 0x38462000, 0x38464000, 0x38466000, 0x38468000, 0x3846a000, + 0x3846c000, 0x3846e000, 0x38470000, 0x38472000, 0x38474000, 0x38476000, + 0x38478000, 0x3847a000, 0x3847c000, 0x3847e000, 0x38480000, 0x38482000, + 0x38484000, 0x38486000, 0x38488000, 0x3848a000, 0x3848c000, 0x3848e000, + 0x38490000, 0x38492000, 0x38494000, 0x38496000, 0x38498000, 0x3849a000, + 0x3849c000, 0x3849e000, 0x384a0000, 0x384a2000, 0x384a4000, 0x384a6000, + 0x384a8000, 0x384aa000, 0x384ac000, 0x384ae000, 0x384b0000, 0x384b2000, + 0x384b4000, 0x384b6000, 0x384b8000, 0x384ba000, 0x384bc000, 0x384be000, + 0x384c0000, 0x384c2000, 0x384c4000, 0x384c6000, 0x384c8000, 0x384ca000, + 0x384cc000, 0x384ce000, 0x384d0000, 0x384d2000, 0x384d4000, 0x384d6000, + 0x384d8000, 0x384da000, 0x384dc000, 0x384de000, 0x384e0000, 0x384e2000, + 0x384e4000, 0x384e6000, 0x384e8000, 0x384ea000, 0x384ec000, 0x384ee000, + 0x384f0000, 0x384f2000, 0x384f4000, 0x384f6000, 0x384f8000, 0x384fa000, + 0x384fc000, 0x384fe000, 0x38500000, 0x38502000, 0x38504000, 0x38506000, + 0x38508000, 0x3850a000, 0x3850c000, 0x3850e000, 0x38510000, 0x38512000, + 0x38514000, 0x38516000, 0x38518000, 0x3851a000, 0x3851c000, 0x3851e000, + 0x38520000, 0x38522000, 0x38524000, 0x38526000, 0x38528000, 0x3852a000, + 0x3852c000, 0x3852e000, 0x38530000, 0x38532000, 0x38534000, 0x38536000, + 0x38538000, 0x3853a000, 0x3853c000, 0x3853e000, 0x38540000, 0x38542000, + 0x38544000, 0x38546000, 0x38548000, 0x3854a000, 0x3854c000, 0x3854e000, + 0x38550000, 0x38552000, 0x38554000, 0x38556000, 0x38558000, 0x3855a000, + 0x3855c000, 0x3855e000, 0x38560000, 0x38562000, 0x38564000, 0x38566000, + 0x38568000, 0x3856a000, 0x3856c000, 0x3856e000, 0x38570000, 0x38572000, + 0x38574000, 0x38576000, 0x38578000, 0x3857a000, 0x3857c000, 0x3857e000, + 0x38580000, 0x38582000, 0x38584000, 0x38586000, 0x38588000, 0x3858a000, + 0x3858c000, 0x3858e000, 0x38590000, 0x38592000, 0x38594000, 0x38596000, + 0x38598000, 0x3859a000, 0x3859c000, 0x3859e000, 0x385a0000, 0x385a2000, + 0x385a4000, 0x385a6000, 0x385a8000, 0x385aa000, 0x385ac000, 0x385ae000, + 0x385b0000, 0x385b2000, 0x385b4000, 0x385b6000, 0x385b8000, 0x385ba000, + 0x385bc000, 0x385be000, 0x385c0000, 0x385c2000, 0x385c4000, 0x385c6000, + 0x385c8000, 0x385ca000, 0x385cc000, 0x385ce000, 0x385d0000, 0x385d2000, + 0x385d4000, 0x385d6000, 0x385d8000, 0x385da000, 0x385dc000, 0x385de000, + 0x385e0000, 0x385e2000, 0x385e4000, 0x385e6000, 0x385e8000, 0x385ea000, + 0x385ec000, 0x385ee000, 0x385f0000, 0x385f2000, 0x385f4000, 0x385f6000, + 0x385f8000, 0x385fa000, 0x385fc000, 0x385fe000, 0x38600000, 0x38602000, + 0x38604000, 0x38606000, 0x38608000, 0x3860a000, 0x3860c000, 0x3860e000, + 0x38610000, 0x38612000, 0x38614000, 0x38616000, 0x38618000, 0x3861a000, + 0x3861c000, 0x3861e000, 0x38620000, 0x38622000, 0x38624000, 0x38626000, + 0x38628000, 0x3862a000, 0x3862c000, 0x3862e000, 0x38630000, 0x38632000, + 0x38634000, 0x38636000, 0x38638000, 0x3863a000, 0x3863c000, 0x3863e000, + 0x38640000, 0x38642000, 0x38644000, 0x38646000, 0x38648000, 0x3864a000, + 0x3864c000, 0x3864e000, 0x38650000, 0x38652000, 0x38654000, 0x38656000, + 0x38658000, 0x3865a000, 0x3865c000, 0x3865e000, 0x38660000, 0x38662000, + 0x38664000, 0x38666000, 0x38668000, 0x3866a000, 0x3866c000, 0x3866e000, + 0x38670000, 0x38672000, 0x38674000, 0x38676000, 0x38678000, 0x3867a000, + 0x3867c000, 0x3867e000, 0x38680000, 0x38682000, 0x38684000, 0x38686000, + 0x38688000, 0x3868a000, 0x3868c000, 0x3868e000, 0x38690000, 0x38692000, + 0x38694000, 0x38696000, 0x38698000, 0x3869a000, 0x3869c000, 0x3869e000, + 0x386a0000, 0x386a2000, 0x386a4000, 0x386a6000, 0x386a8000, 0x386aa000, + 0x386ac000, 0x386ae000, 0x386b0000, 0x386b2000, 0x386b4000, 0x386b6000, + 0x386b8000, 0x386ba000, 0x386bc000, 0x386be000, 0x386c0000, 0x386c2000, + 0x386c4000, 0x386c6000, 0x386c8000, 0x386ca000, 0x386cc000, 0x386ce000, + 0x386d0000, 0x386d2000, 0x386d4000, 0x386d6000, 0x386d8000, 0x386da000, + 0x386dc000, 0x386de000, 0x386e0000, 0x386e2000, 0x386e4000, 0x386e6000, + 0x386e8000, 0x386ea000, 0x386ec000, 0x386ee000, 0x386f0000, 0x386f2000, + 0x386f4000, 0x386f6000, 0x386f8000, 0x386fa000, 0x386fc000, 0x386fe000, + 0x38700000, 0x38702000, 0x38704000, 0x38706000, 0x38708000, 0x3870a000, + 0x3870c000, 0x3870e000, 0x38710000, 0x38712000, 0x38714000, 0x38716000, + 0x38718000, 0x3871a000, 0x3871c000, 0x3871e000, 0x38720000, 0x38722000, + 0x38724000, 0x38726000, 0x38728000, 0x3872a000, 0x3872c000, 0x3872e000, + 0x38730000, 0x38732000, 0x38734000, 0x38736000, 0x38738000, 0x3873a000, + 0x3873c000, 0x3873e000, 0x38740000, 0x38742000, 0x38744000, 0x38746000, + 0x38748000, 0x3874a000, 0x3874c000, 0x3874e000, 0x38750000, 0x38752000, + 0x38754000, 0x38756000, 0x38758000, 0x3875a000, 0x3875c000, 0x3875e000, + 0x38760000, 0x38762000, 0x38764000, 0x38766000, 0x38768000, 0x3876a000, + 0x3876c000, 0x3876e000, 0x38770000, 0x38772000, 0x38774000, 0x38776000, + 0x38778000, 0x3877a000, 0x3877c000, 0x3877e000, 0x38780000, 0x38782000, + 0x38784000, 0x38786000, 0x38788000, 0x3878a000, 0x3878c000, 0x3878e000, + 0x38790000, 0x38792000, 0x38794000, 0x38796000, 0x38798000, 0x3879a000, + 0x3879c000, 0x3879e000, 0x387a0000, 0x387a2000, 0x387a4000, 0x387a6000, + 0x387a8000, 0x387aa000, 0x387ac000, 0x387ae000, 0x387b0000, 0x387b2000, + 0x387b4000, 0x387b6000, 0x387b8000, 0x387ba000, 0x387bc000, 0x387be000, + 0x387c0000, 0x387c2000, 0x387c4000, 0x387c6000, 0x387c8000, 0x387ca000, + 0x387cc000, 0x387ce000, 0x387d0000, 0x387d2000, 0x387d4000, 0x387d6000, + 0x387d8000, 0x387da000, 0x387dc000, 0x387de000, 0x387e0000, 0x387e2000, + 0x387e4000, 0x387e6000, 0x387e8000, 0x387ea000, 0x387ec000, 0x387ee000, + 0x387f0000, 0x387f2000, 0x387f4000, 0x387f6000, 0x387f8000, 0x387fa000, + 0x387fc000, 0x387fe000}; + +const uint16_t g_offset_table[64] = { + 0, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 0, + 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, + 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024}; + +const uint32_t g_exponent_table[64] = { + 0x0, 0x800000, 0x1000000, 0x1800000, 0x2000000, 0x2800000, + 0x3000000, 0x3800000, 0x4000000, 0x4800000, 0x5000000, 0x5800000, + 0x6000000, 0x6800000, 0x7000000, 0x7800000, 0x8000000, 0x8800000, + 0x9000000, 0x9800000, 0xa000000, 0xa800000, 0xb000000, 0xb800000, + 0xc000000, 0xc800000, 0xd000000, 0xd800000, 0xe000000, 0xe800000, + 0xf000000, 0x47800000, 0x80000000, 0x80800000, 0x81000000, 0x81800000, + 0x82000000, 0x82800000, 0x83000000, 0x83800000, 0x84000000, 0x84800000, + 0x85000000, 0x85800000, 0x86000000, 0x86800000, 0x87000000, 0x87800000, + 0x88000000, 0x88800000, 0x89000000, 0x89800000, 0x8a000000, 0x8a800000, + 0x8b000000, 0x8b800000, 0x8c000000, 0x8c800000, 0x8d000000, 0x8d800000, + 0x8e000000, 0x8e800000, 0x8f000000, 0xc7800000}; + +float ConvertHalfFloatToFloat(uint16_t half) { + uint32_t temp = + g_mantissa_table[g_offset_table[half >> 10] + (half & 0x3ff)] + + g_exponent_table[half >> 10]; + return *(reinterpret_cast<float*>(&temp)); +} + /* BEGIN CODE SHARED WITH MOZILLA FIREFOX */ // The following packing and unpacking routines are expressed in terms of @@ -659,10 +1098,70 @@ void Unpack<WebGLImageConversion::kDataFormatRGBA2_10_10_10, uint32_t, float>( } } +// Used for non-trivial conversions of RGBA16F data. +template <> +void Unpack<WebGLImageConversion::kDataFormatRGBA16F, uint16_t, float>( + const uint16_t* source, + float* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ConvertHalfFloatToFloat(source[0]); + destination[1] = ConvertHalfFloatToFloat(source[1]); + destination[2] = ConvertHalfFloatToFloat(source[2]); + destination[3] = ConvertHalfFloatToFloat(source[3]); + source += 4; + destination += 4; + } +} + +// Used for the trivial conversion of RGBA16F data to RGBA8. +template <> +void Unpack<WebGLImageConversion::kDataFormatRGBA16F, uint16_t, uint8_t>( + const uint16_t* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = + ClampAndScaleFloat<uint8_t>(ConvertHalfFloatToFloat(source[0])); + destination[1] = + ClampAndScaleFloat<uint8_t>(ConvertHalfFloatToFloat(source[1])); + destination[2] = + ClampAndScaleFloat<uint8_t>(ConvertHalfFloatToFloat(source[2])); + destination[3] = + ClampAndScaleFloat<uint8_t>(ConvertHalfFloatToFloat(source[3])); + source += 4; + destination += 4; + } +} + //---------------------------------------------------------------------- // Pixel packing routines. // +// All of the formats below refer to the format of the texture being +// uploaded. Only the formats that accept DOM sources (images, videos, +// ImageBitmap, etc.) need to: +// +// (a) support conversions from "other" formats than the destination +// format, since the other cases are simply handling Y-flips or alpha +// premultiplication of data supplied via ArrayBufferView +// +// (b) support the kAlphaDoUnmultiply operation, which is needed because +// there are some DOM-related data sources (like 2D canvas) which are +// stored in premultiplied form. Note that the alpha-only formats +// inherently don't need to support the kAlphaDoUnmultiply operation. +// +// The formats that accept DOM-related inputs are in the table for +// texImage2D taking TexImageSource in the WebGL 2.0 specification, plus +// all of the formats in the WebGL 1.0 specification, including legacy +// formats like luminance, alpha and luminance-alpha formats (which are +// renamed in the DataFormat enum to things like "red-alpha"). Extensions +// like EXT_texture_norm16 add to the supported formats +// +// Currently, those texture formats to which DOM-related inputs can be +// uploaded have to support two basic input formats coming from the rest of +// the browser: uint8_t, for RGBA8, and float, for RGBA16F. + template <int format, int alphaOp, typename SourceType, typename DstType> void Pack(const SourceType*, DstType*, unsigned) { NOTREACHED(); @@ -683,6 +1182,20 @@ void Pack<WebGLImageConversion::kDataFormatA8, } template <> +void Pack<WebGLImageConversion::kDataFormatA8, + WebGLImageConversion::kAlphaDoNothing, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[3]); + source += 4; + destination += 1; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatR8, WebGLImageConversion::kAlphaDoNothing, uint8_t, @@ -698,6 +1211,20 @@ void Pack<WebGLImageConversion::kDataFormatR8, template <> void Pack<WebGLImageConversion::kDataFormatR8, + WebGLImageConversion::kAlphaDoNothing, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0]); + source += 4; + destination += 1; + } +} + +template <> +void Pack<WebGLImageConversion::kDataFormatR8, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, @@ -713,7 +1240,21 @@ void Pack<WebGLImageConversion::kDataFormatR8, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatR8, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + uint8_t source_r = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + destination[0] = source_r; + source += 4; + destination += 1; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatR8, WebGLImageConversion::kAlphaDoUnmultiply, @@ -738,6 +1279,22 @@ void Pack<WebGLImageConversion::kDataFormatR8, } template <> +void Pack<WebGLImageConversion::kDataFormatR8, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + uint8_t source_r = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + destination[0] = source_r; + source += 4; + destination += 1; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRA8, WebGLImageConversion::kAlphaDoNothing, uint8_t, @@ -754,6 +1311,21 @@ void Pack<WebGLImageConversion::kDataFormatRA8, template <> void Pack<WebGLImageConversion::kDataFormatRA8, + WebGLImageConversion::kAlphaDoNothing, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0]); + destination[1] = ClampAndScaleFloat<uint8_t>(source[3]); + source += 4; + destination += 2; + } +} + +template <> +void Pack<WebGLImageConversion::kDataFormatRA8, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, @@ -770,7 +1342,21 @@ void Pack<WebGLImageConversion::kDataFormatRA8, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatRA8, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + destination[1] = ClampAndScaleFloat<uint8_t>(source[3]); + source += 4; + destination += 2; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatRA8, WebGLImageConversion::kAlphaDoUnmultiply, @@ -796,6 +1382,23 @@ void Pack<WebGLImageConversion::kDataFormatRA8, } template <> +void Pack<WebGLImageConversion::kDataFormatRA8, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + uint8_t source_r = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + destination[0] = source_r; + destination[1] = ClampAndScaleFloat<uint8_t>(source[3]); + source += 4; + destination += 2; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRGB8, WebGLImageConversion::kAlphaDoNothing, uint8_t, @@ -813,6 +1416,22 @@ void Pack<WebGLImageConversion::kDataFormatRGB8, template <> void Pack<WebGLImageConversion::kDataFormatRGB8, + WebGLImageConversion::kAlphaDoNothing, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0]); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1]); + destination[2] = ClampAndScaleFloat<uint8_t>(source[2]); + source += 4; + destination += 3; + } +} + +template <> +void Pack<WebGLImageConversion::kDataFormatRGB8, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, @@ -834,7 +1453,22 @@ void Pack<WebGLImageConversion::kDataFormatRGB8, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatRGB8, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1] * source[3]); + destination[2] = ClampAndScaleFloat<uint8_t>(source[2] * source[3]); + source += 4; + destination += 3; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatRGB8, WebGLImageConversion::kAlphaDoUnmultiply, @@ -859,6 +1493,23 @@ void Pack<WebGLImageConversion::kDataFormatRGB8, } template <> +void Pack<WebGLImageConversion::kDataFormatRGB8, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + destination[0] = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1] * scale_factor); + destination[2] = ClampAndScaleFloat<uint8_t>(source[2] * scale_factor); + source += 4; + destination += 3; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRGBA8, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, @@ -882,7 +1533,23 @@ void Pack<WebGLImageConversion::kDataFormatRGBA8, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatRGBA8, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1] * source[3]); + destination[2] = ClampAndScaleFloat<uint8_t>(source[2] * source[3]); + destination[3] = ClampAndScaleFloat<uint8_t>(source[3]); + source += 4; + destination += 4; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatRGBA8, WebGLImageConversion::kAlphaDoUnmultiply, @@ -914,6 +1581,24 @@ void Pack<WebGLImageConversion::kDataFormatRGBA8, } template <> +void Pack<WebGLImageConversion::kDataFormatRGBA8, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + destination[0] = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1] * scale_factor); + destination[2] = ClampAndScaleFloat<uint8_t>(source[2] * scale_factor); + destination[3] = ClampAndScaleFloat<uint8_t>(source[3]); + source += 4; + destination += 4; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRGBA4444, WebGLImageConversion::kAlphaDoNothing, uint8_t, @@ -938,6 +1623,25 @@ void Pack<WebGLImageConversion::kDataFormatRGBA4444, template <> void Pack<WebGLImageConversion::kDataFormatRGBA4444, + WebGLImageConversion::kAlphaDoNothing, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0]); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1]); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2]); + uint8_t a = ClampAndScaleFloat<uint8_t>(source[3]); + *destination = + (((r & 0xF0) << 8) | ((g & 0xF0) << 4) | (b & 0xF0) | (a >> 4)); + source += 4; + destination += 1; + } +} + +template <> +void Pack<WebGLImageConversion::kDataFormatRGBA4444, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, @@ -958,7 +1662,25 @@ void Pack<WebGLImageConversion::kDataFormatRGBA4444, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatRGBA4444, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1] * source[3]); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2] * source[3]); + uint8_t a = ClampAndScaleFloat<uint8_t>(source[3]); + *destination = + (((r & 0xF0) << 8) | ((g & 0xF0) << 4) | (b & 0xF0) | (a >> 4)); + source += 4; + destination += 1; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatRGBA4444, WebGLImageConversion::kAlphaDoUnmultiply, @@ -982,6 +1704,26 @@ void Pack<WebGLImageConversion::kDataFormatRGBA4444, } template <> +void Pack<WebGLImageConversion::kDataFormatRGBA4444, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1] * scale_factor); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2] * scale_factor); + uint8_t a = ClampAndScaleFloat<uint8_t>(source[3]); + *destination = + (((r & 0xF0) << 8) | ((g & 0xF0) << 4) | (b & 0xF0) | (a >> 4)); + source += 4; + destination += 1; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRGBA5551, WebGLImageConversion::kAlphaDoNothing, uint8_t, @@ -1006,6 +1748,25 @@ void Pack<WebGLImageConversion::kDataFormatRGBA5551, template <> void Pack<WebGLImageConversion::kDataFormatRGBA5551, + WebGLImageConversion::kAlphaDoNothing, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0]); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1]); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2]); + uint8_t a = ClampAndScaleFloat<uint8_t>(source[3]); + *destination = + (((r & 0xF8) << 8) | ((g & 0xF8) << 3) | ((b & 0xF8) >> 2) | (a >> 7)); + source += 4; + destination += 1; + } +} + +template <> +void Pack<WebGLImageConversion::kDataFormatRGBA5551, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, @@ -1026,7 +1787,25 @@ void Pack<WebGLImageConversion::kDataFormatRGBA5551, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatRGBA5551, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1] * source[3]); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2] * source[3]); + uint8_t a = ClampAndScaleFloat<uint8_t>(source[3]); + *destination = + (((r & 0xF8) << 8) | ((g & 0xF8) << 3) | ((b & 0xF8) >> 2) | (a >> 7)); + source += 4; + destination += 1; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatRGBA5551, WebGLImageConversion::kAlphaDoUnmultiply, @@ -1050,6 +1829,26 @@ void Pack<WebGLImageConversion::kDataFormatRGBA5551, } template <> +void Pack<WebGLImageConversion::kDataFormatRGBA5551, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1] * scale_factor); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2] * scale_factor); + uint8_t a = ClampAndScaleFloat<uint8_t>(source[3]); + *destination = + (((r & 0xF8) << 8) | ((g & 0xF8) << 3) | ((b & 0xF8) >> 2) | (a >> 7)); + source += 4; + destination += 1; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRGB565, WebGLImageConversion::kAlphaDoNothing, uint8_t, @@ -1074,6 +1873,23 @@ void Pack<WebGLImageConversion::kDataFormatRGB565, template <> void Pack<WebGLImageConversion::kDataFormatRGB565, + WebGLImageConversion::kAlphaDoNothing, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0]); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1]); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2]); + *destination = (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)); + source += 4; + destination += 1; + } +} + +template <> +void Pack<WebGLImageConversion::kDataFormatRGB565, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, uint16_t>(const uint8_t* source, @@ -1094,7 +1910,23 @@ void Pack<WebGLImageConversion::kDataFormatRGB565, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatRGB565, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1] * source[3]); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2] * source[3]); + *destination = (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)); + source += 4; + destination += 1; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatRGB565, WebGLImageConversion::kAlphaDoUnmultiply, @@ -1118,6 +1950,24 @@ void Pack<WebGLImageConversion::kDataFormatRGB565, } template <> +void Pack<WebGLImageConversion::kDataFormatRGB565, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + uint8_t r = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + uint8_t g = ClampAndScaleFloat<uint8_t>(source[1] * scale_factor); + uint8_t b = ClampAndScaleFloat<uint8_t>(source[2] * scale_factor); + *destination = (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)); + source += 4; + destination += 1; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRGB32F, WebGLImageConversion::kAlphaDoNothing, float, @@ -1516,6 +2366,9 @@ void Pack<WebGLImageConversion::kDataFormatA16F, } } +// Can not be targeted by DOM uploads, so does not need to support float +// input data. + template <> void Pack<WebGLImageConversion::kDataFormatRGBA8_S, WebGLImageConversion::kAlphaDoPremultiply, @@ -1559,6 +2412,26 @@ void Pack<WebGLImageConversion::kDataFormatRGBA16, } template <> +void Pack<WebGLImageConversion::kDataFormatRGBA16, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint16_t>(const float* source, + uint16_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint16_t>(source[0] * source[3]); + destination[1] = ClampAndScaleFloat<uint16_t>(source[1] * source[3]); + destination[2] = ClampAndScaleFloat<uint16_t>(source[2] * source[3]); + destination[3] = ClampAndScaleFloat<uint16_t>(source[3]); + source += 4; + destination += 4; + } +} + +// Can not be targeted by DOM uploads, so does not need to support float +// input data. + +template <> void Pack<WebGLImageConversion::kDataFormatRGBA16_S, WebGLImageConversion::kAlphaDoPremultiply, int16_t, @@ -1579,6 +2452,9 @@ void Pack<WebGLImageConversion::kDataFormatRGBA16_S, } } +// Can not be targeted by DOM uploads, so does not need to support float +// input data. + template <> void Pack<WebGLImageConversion::kDataFormatRGBA32, WebGLImageConversion::kAlphaDoPremultiply, @@ -1600,6 +2476,9 @@ void Pack<WebGLImageConversion::kDataFormatRGBA32, } } +// Can not be targeted by DOM uploads, so does not need to support float +// input data. + template <> void Pack<WebGLImageConversion::kDataFormatRGBA32_S, WebGLImageConversion::kAlphaDoPremultiply, @@ -1693,6 +2572,21 @@ void Pack<WebGLImageConversion::kDataFormatRG8, template <> void Pack<WebGLImageConversion::kDataFormatRG8, + WebGLImageConversion::kAlphaDoNothing, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0]); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1]); + source += 4; + destination += 2; + } +} + +template <> +void Pack<WebGLImageConversion::kDataFormatRG8, WebGLImageConversion::kAlphaDoPremultiply, uint8_t, uint8_t>(const uint8_t* source, @@ -1709,7 +2603,21 @@ void Pack<WebGLImageConversion::kDataFormatRG8, } } -// FIXME: this routine is lossy and must be removed. +template <> +void Pack<WebGLImageConversion::kDataFormatRG8, + WebGLImageConversion::kAlphaDoPremultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + destination[0] = ClampAndScaleFloat<uint8_t>(source[0] * source[3]); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1] * source[3]); + source += 4; + destination += 2; + } +} + template <> void Pack<WebGLImageConversion::kDataFormatRG8, WebGLImageConversion::kAlphaDoUnmultiply, @@ -1730,6 +2638,22 @@ void Pack<WebGLImageConversion::kDataFormatRG8, } template <> +void Pack<WebGLImageConversion::kDataFormatRG8, + WebGLImageConversion::kAlphaDoUnmultiply, + float, + uint8_t>(const float* source, + uint8_t* destination, + unsigned pixels_per_row) { + for (unsigned i = 0; i < pixels_per_row; ++i) { + float scale_factor = source[3] ? 1.0f / source[3] : 1.0f; + destination[0] = ClampAndScaleFloat<uint8_t>(source[0] * scale_factor); + destination[1] = ClampAndScaleFloat<uint8_t>(source[1] * scale_factor); + source += 4; + destination += 2; + } +} + +template <> void Pack<WebGLImageConversion::kDataFormatRG16F, WebGLImageConversion::kAlphaDoNothing, float, @@ -1760,7 +2684,6 @@ void Pack<WebGLImageConversion::kDataFormatRG16F, } } -// FIXME: this routine is lossy and must be removed. template <> void Pack<WebGLImageConversion::kDataFormatRG16F, WebGLImageConversion::kAlphaDoUnmultiply, @@ -1808,7 +2731,6 @@ void Pack<WebGLImageConversion::kDataFormatRG32F, } } -// FIXME: this routine is lossy and must be removed. template <> void Pack<WebGLImageConversion::kDataFormatRG32F, WebGLImageConversion::kAlphaDoUnmultiply, @@ -2360,6 +3282,8 @@ void FormatConverter::Convert(WebGLImageConversion::DataFormat src_format, FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA32F) FORMATCONVERTER_CASE_SRCFORMAT( WebGLImageConversion::kDataFormatRGBA2_10_10_10) + // Only used by ImageBitmap, when colorspace conversion is needed. + FORMATCONVERTER_CASE_SRCFORMAT(WebGLImageConversion::kDataFormatRGBA16F) default: NOTREACHED(); } @@ -2462,6 +3386,8 @@ void FormatConverter::Convert() { NOTREACHED(); return; } + // Note that ImageBitmaps with SrcFormat==kDataFormatRGBA16F return + // false for IsFloatFormat since the input data is uint16_t. if (!IsFloatFormat<DstFormat>::value && IsFloatFormat<SrcFormat>::value) { NOTREACHED(); return; @@ -2470,7 +3396,7 @@ void FormatConverter::Convert() { // Only textures uploaded from DOM elements or ImageData can allow DstFormat // != SrcFormat. const bool src_format_comes_from_dom_element_or_image_data = - WebGLImageConversion::SrcFormatComeFromDOMElementOrImageData(SrcFormat); + WebGLImageConversion::SrcFormatComesFromDOMElementOrImageData(SrcFormat); if (!src_format_comes_from_dom_element_or_image_data && SrcFormat != DstFormat) { NOTREACHED(); diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h index 2c8f9617f3d..6ac0093ee61 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h @@ -194,12 +194,14 @@ class PLATFORM_EXPORT WebGLImageConversion final { unsigned* padding_in_bytes, unsigned* skip_size_in_bytes); - // Check if the format is one of the formats from the ImageData or DOM - // elements. The format from ImageData is always RGBA8. The formats from DOM - // elements vary with Graphics ports, but can only be RGBA8 or BGRA8. - static ALWAYS_INLINE bool SrcFormatComeFromDOMElementOrImageData( + // Check if the format is one of the formats from ImageData DOM elements, or + // ImageBitmap. The format from ImageData is always RGBA8. The formats from + // DOM elements vary with Graphics ports, but can only be RGBA8 or BGRA8. + // ImageBitmap can use RGBA16F when colorspace conversion is performed. + static ALWAYS_INLINE bool SrcFormatComesFromDOMElementOrImageData( DataFormat src_format) { - return src_format == kDataFormatBGRA8 || src_format == kDataFormatRGBA8; + return src_format == kDataFormatBGRA8 || src_format == kDataFormatRGBA8 || + src_format == kDataFormatRGBA16F; } // The input can be either format or internalformat. diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc index e6a4a67905d..a767c2e5b32 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc @@ -21,13 +21,42 @@ uint64_t AlignWebGPUBytesPerRow(uint64_t bytesPerRow) { << kDawnBytesPerRowAlignmentBits; } +SkColorType DawnColorTypeToSkColorType(WGPUTextureFormat dawn_format) { + switch (dawn_format) { + case WGPUTextureFormat_RGBA8Unorm: + // According to WebGPU spec, format with -srgb suffix will do color + // space conversion when reading and writing in shader. In this uploading + // path, we should keep the conversion happening in canvas color space and + // leave the srgb color space conversion to the GPU. + case WGPUTextureFormat_RGBA8UnormSrgb: + return SkColorType::kRGBA_8888_SkColorType; + case WGPUTextureFormat_BGRA8Unorm: + case WGPUTextureFormat_BGRA8UnormSrgb: + return SkColorType::kBGRA_8888_SkColorType; + case WGPUTextureFormat_RGB10A2Unorm: + return SkColorType::kRGBA_1010102_SkColorType; + case WGPUTextureFormat_RGBA16Float: + return SkColorType::kRGBA_F16_SkColorType; + case WGPUTextureFormat_RGBA32Float: + return SkColorType::kRGBA_F32_SkColorType; + case WGPUTextureFormat_RG8Unorm: + return SkColorType::kR8G8_unorm_SkColorType; + case WGPUTextureFormat_RG16Float: + return SkColorType::kR16G16_float_SkColorType; + default: + return SkColorType::kUnknown_SkColorType; + } +} + } // anonymous namespace WebGPUImageUploadSizeInfo ComputeImageBitmapWebGPUUploadSizeInfo( const IntRect& rect, - const CanvasColorParams& color_params) { + const WGPUTextureFormat& destination_format) { WebGPUImageUploadSizeInfo info; - uint64_t bytes_per_pixel = color_params.BytesPerPixel(); + + uint64_t bytes_per_pixel = DawnTextureFormatBytesPerPixel(destination_format); + DCHECK_NE(bytes_per_pixel, 0u); uint64_t bytes_per_row = AlignWebGPUBytesPerRow(rect.Width() * bytes_per_pixel); @@ -42,31 +71,33 @@ WebGPUImageUploadSizeInfo ComputeImageBitmapWebGPUUploadSizeInfo( return info; } -bool CopyBytesFromImageBitmapForWebGPU(scoped_refptr<StaticBitmapImage> image, - base::span<uint8_t> dst, - const IntRect& rect, - const CanvasColorParams& color_params) { +bool CopyBytesFromImageBitmapForWebGPU( + scoped_refptr<StaticBitmapImage> image, + base::span<uint8_t> dst, + const IntRect& rect, + const CanvasColorParams& color_params, + const WGPUTextureFormat destination_format) { DCHECK(image); DCHECK_GT(dst.size(), static_cast<size_t>(0)); DCHECK(image->width() - rect.X() >= rect.Width()); DCHECK(image->height() - rect.Y() >= rect.Height()); WebGPUImageUploadSizeInfo wgpu_info = - ComputeImageBitmapWebGPUUploadSizeInfo(rect, color_params); + ComputeImageBitmapWebGPUUploadSizeInfo(rect, destination_format); DCHECK_EQ(static_cast<uint64_t>(dst.size()), wgpu_info.size_in_bytes); // Prepare extract data from SkImage. - // TODO(shaobo.yan@intel.com): Make sure the data is in the correct format for - // copying to WebGPU - SkColorType color_type = - (color_params.GetSkColorType() == kRGBA_F16_SkColorType) - ? kRGBA_F16_SkColorType - : kRGBA_8888_SkColorType; + SkColorType sk_color_type = DawnColorTypeToSkColorType(destination_format); + if (sk_color_type == kUnknown_SkColorType) { + return false; + } // Read pixel request dst info. - // TODO(shaobo.yan@intel.com): Use Skia to do transform and color conversion. + // Keep premulalpha config and color space from imageBitmap and using dest + // texture color type. This can help do conversions in ReadPixels. SkImageInfo info = SkImageInfo::Make( - rect.Width(), rect.Height(), color_type, kUnpremul_SkAlphaType, + rect.Width(), rect.Height(), sk_color_type, + image->IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType, color_params.GetSkColorSpaceForSkSurfaces()); sk_sp<SkImage> sk_image = image->PaintImageForCurrentFrame().GetSkImage(); @@ -84,6 +115,27 @@ bool CopyBytesFromImageBitmapForWebGPU(scoped_refptr<StaticBitmapImage> image, return true; } +uint64_t DawnTextureFormatBytesPerPixel(const WGPUTextureFormat color_type) { + switch (color_type) { + case WGPUTextureFormat_RG8Unorm: + return 2; + case WGPUTextureFormat_RGBA8Unorm: + case WGPUTextureFormat_RGBA8UnormSrgb: + case WGPUTextureFormat_BGRA8Unorm: + case WGPUTextureFormat_BGRA8UnormSrgb: + case WGPUTextureFormat_RGB10A2Unorm: + case WGPUTextureFormat_RG16Float: + return 4; + case WGPUTextureFormat_RGBA16Float: + return 8; + case WGPUTextureFormat_RGBA32Float: + return 16; + default: + NOTREACHED(); + return 0; + } +} + DawnTextureFromImageBitmap::DawnTextureFromImageBitmap( scoped_refptr<DawnControlClientHolder> dawn_control_client, uint64_t device_client_id) diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h index 57cce174508..836ef713646 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.h @@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_IMAGE_BITMAP_HANDLER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGPU_IMAGE_BITMAP_HANDLER_H_ +#include <dawn/webgpu.h> + #include "base/containers/span.h" #include "gpu/command_buffer/common/mailbox.h" #include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h" @@ -23,13 +25,18 @@ class IntRect; class StaticBitmapImage; WebGPUImageUploadSizeInfo PLATFORM_EXPORT -ComputeImageBitmapWebGPUUploadSizeInfo(const IntRect& rect, - const CanvasColorParams& color_params); +ComputeImageBitmapWebGPUUploadSizeInfo( + const IntRect& rect, + const WGPUTextureFormat& destination_format); bool PLATFORM_EXPORT CopyBytesFromImageBitmapForWebGPU(scoped_refptr<StaticBitmapImage> image, base::span<uint8_t> dst, const IntRect& rect, - const CanvasColorParams& color_params); + const CanvasColorParams& color_params, + const WGPUTextureFormat destination_format); + +uint64_t PLATFORM_EXPORT +DawnTextureFormatBytesPerPixel(const WGPUTextureFormat color_type); class PLATFORM_EXPORT DawnTextureFromImageBitmap : public RefCounted<DawnTextureFromImageBitmap> { diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc index 411431ff306..c6ab596d479 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler_test.cc @@ -24,8 +24,6 @@ using testing::Return; namespace blink { -static constexpr uint64_t kMaxArrayLength = 40000; - namespace { gpu::SyncToken GenTestSyncToken(GLbyte id) { gpu::SyncToken token; @@ -77,58 +75,244 @@ class MockWebGPUInterface : public gpu::webgpu::WebGPUInterfaceStub { GLuint texture_id, GLuint texture_generation)); }; + +// The six reference pixels are: red, green, blue, white, black. +static const uint8_t rgba8[] = { + 0xFF, 0x00, 0x00, 0xFF, // Red + 0x00, 0xFF, 0x00, 0xFF, // Green + 0x00, 0x00, 0xFF, 0xFF, // Blue + 0x00, 0x00, 0x00, 0xFF, // White + 0xFF, 0xFF, 0xFF, 0xFF, // Opaque Black + 0xFF, 0xFF, 0xFF, 0x00, // Transparent Black +}; + +static const uint8_t bgra8[] = { + 0x00, 0x00, 0xFF, 0xFF, // Red + 0x00, 0xFF, 0x00, 0xFF, // Green + 0xFF, 0x00, 0x00, 0xFF, // Blue + 0x00, 0x00, 0x00, 0xFF, // White + 0xFF, 0xFF, 0xFF, 0xFF, // Opaque Black + 0xFF, 0xFF, 0xFF, 0x00, // Transparent Black +}; + +static const uint8_t rgb10a2[] = { + 0xFF, 0x03, 0x00, 0xC0, // Red + 0x00, 0xFC, 0x0F, 0xC0, // Green + 0x00, 0x00, 0xF0, 0xFF, // Blue + 0x00, 0x00, 0x00, 0xC0, // White + 0xFF, 0xFF, 0xFF, 0xFF, // Opaque Black + 0xFF, 0xFF, 0xFF, 0x3F, // Transparent Black +}; + +static const uint16_t f16[] = { + 0x3C00, 0x0000, 0x0000, 0x3C00, // Red + 0x0000, 0x3C00, 0x0000, 0x3C00, // Green + 0x0000, 0x0000, 0x3C00, 0x3C00, // Blue + 0x0000, 0x0000, 0x0000, 0x3C00, // White + 0x3C00, 0x3C00, 0x3C00, 0x3C00, // Opaque Black + 0x3C00, 0x3C00, 0x3C00, 0x0000, // Transparent Black +}; + +static const float f32[] = { + 1.0f, 0.0f, 0.0f, 1.0f, // Red + 0.0f, 1.0f, 0.0f, 1.0f, // Green + 0.0f, 0.0f, 1.0f, 1.0f, // Blue + 0.0f, 0.0f, 0.0f, 1.0f, // White + 1.0f, 1.0f, 1.0f, 1.0f, // Opaque Black + 1.0f, 1.0f, 1.0f, 0.0f, // Transparent Black +}; + +static const uint8_t rg8[] = { + 0xFF, 0x00, // Red + 0x00, 0xFF, // Green + 0x00, 0x00, // No Blue + 0x00, 0x00, // White + 0xFF, 0xFF, // Opaque Black + 0xFF, 0xFF, // Transparent Black +}; + +static const uint16_t rg16f[] = { + 0x3C00, 0x0000, // Red + 0x0000, 0x3C00, // Green + 0x0000, 0x0000, // No Blue + 0x0000, 0x0000, // White + 0x3C00, 0x3C00, // Opaque Black + 0x3C00, 0x3C00, // Transparent Black +}; + +base::span<const uint8_t> GetDstContent(WGPUTextureFormat format) { + switch (format) { + case WGPUTextureFormat_RG8Unorm: + return base::span<const uint8_t>(rg8, sizeof(rg8)); + case WGPUTextureFormat_RGBA8Unorm: + // We need to ensure no color space conversion happens + // during imageBitmap uploading. + case WGPUTextureFormat_RGBA8UnormSrgb: + return base::span<const uint8_t>(rgba8, sizeof(rgba8)); + case WGPUTextureFormat_BGRA8Unorm: + case WGPUTextureFormat_BGRA8UnormSrgb: + return base::span<const uint8_t>(bgra8, sizeof(bgra8)); + case WGPUTextureFormat_RGB10A2Unorm: + return base::span<const uint8_t>(rgb10a2, sizeof(rgb10a2)); + case WGPUTextureFormat_RG16Float: + return base::span<const uint8_t>(reinterpret_cast<const uint8_t*>(rg16f), + sizeof(rg16f)); + case WGPUTextureFormat_RGBA16Float: + return base::span<const uint8_t>(reinterpret_cast<const uint8_t*>(f16), + sizeof(f16)); + case WGPUTextureFormat_RGBA32Float: + return base::span<const uint8_t>(reinterpret_cast<const uint8_t*>(f32), + sizeof(f32)); + default: + NOTREACHED(); + return {}; + } +} + +base::span<const uint8_t> GetSrcPixelContent(SkColorType format) { + switch (format) { + case SkColorType::kRGBA_8888_SkColorType: + return base::span<const uint8_t>(rgba8, sizeof(rgba8)); + case SkColorType::kBGRA_8888_SkColorType: + return base::span<const uint8_t>(bgra8, sizeof(bgra8)); + case SkColorType::kRGBA_F16_SkColorType: + return base::span<const uint8_t>(reinterpret_cast<const uint8_t*>(f16), + sizeof(f16)); + default: + NOTREACHED(); + return {}; + } +} + +CanvasPixelFormat SkColorTypeToCanvasPixelFormat(SkColorType format) { + switch (format) { + case SkColorType::kRGBA_8888_SkColorType: + return CanvasPixelFormat::kRGBA8; + case SkColorType::kBGRA_8888_SkColorType: + return CanvasPixelFormat::kBGRA8; + case SkColorType::kRGBA_F16_SkColorType: + return CanvasPixelFormat::kF16; + default: + NOTREACHED(); + return CanvasPixelFormat::kRGBA8; + } +} } // anonymous namespace class WebGPUImageBitmapHandlerTest : public testing::Test { protected: void SetUp() override {} - void VerifyCopyBytesForWebGPU(uint64_t width, - uint64_t height, - SkImageInfo info, - CanvasColorParams param, - IntRect copyRect) { + void VerifyCopyBytesForCanvasColorParams(uint64_t width, + uint64_t height, + SkImageInfo info, + CanvasColorParams param, + IntRect copy_rect, + WGPUTextureFormat color_type) { const uint64_t content_length = width * height * param.BytesPerPixel(); - std::array<uint8_t, kMaxArrayLength> contents = {0}; + std::vector<uint8_t> contents(content_length, 0); // Initialize contents. for (size_t i = 0; i < content_length; ++i) { contents[i] = i % std::numeric_limits<uint8_t>::max(); } + VerifyCopyBytes(width, height, info, param, copy_rect, color_type, + base::span<uint8_t>(contents.data(), content_length), + base::span<uint8_t>(contents.data(), content_length)); + } + + void VerifyCopyBytes(uint64_t width, + uint64_t height, + SkImageInfo info, + CanvasColorParams param, + IntRect copy_rect, + WGPUTextureFormat color_type, + base::span<const uint8_t> contents, + base::span<const uint8_t> expected_value) { + uint64_t bytes_per_pixel = DawnTextureFormatBytesPerPixel(color_type); + ASSERT_EQ(contents.size(), width * height * param.BytesPerPixel()); sk_sp<SkData> image_pixels = - SkData::MakeWithCopy(contents.data(), content_length); + SkData::MakeWithCopy(contents.data(), contents.size()); scoped_refptr<StaticBitmapImage> image = StaticBitmapImage::Create(std::move(image_pixels), info); WebGPUImageUploadSizeInfo wgpu_info = - ComputeImageBitmapWebGPUUploadSizeInfo(copyRect, param); + ComputeImageBitmapWebGPUUploadSizeInfo(copy_rect, color_type); const uint64_t result_length = wgpu_info.size_in_bytes; - std::array<uint8_t, kMaxArrayLength> results = {0}; + std::vector<uint8_t> results(result_length, 0); bool success = CopyBytesFromImageBitmapForWebGPU( - image, base::span<uint8_t>(results.data(), result_length), copyRect, - param); + image, base::span<uint8_t>(results.data(), result_length), copy_rect, + param, color_type); ASSERT_EQ(success, true); // Compare content and results uint32_t bytes_per_row = wgpu_info.wgpu_bytes_per_row; uint32_t content_row_index = - (copyRect.Y() * width + copyRect.X()) * param.BytesPerPixel(); + (copy_rect.Y() * width + copy_rect.X()) * bytes_per_pixel; uint32_t result_row_index = 0; - for (int i = 0; i < copyRect.Height(); ++i) { - EXPECT_EQ(0, - memcmp(&contents[content_row_index], &results[result_row_index], - copyRect.Width() * param.BytesPerPixel())); - content_row_index += width * param.BytesPerPixel(); + for (int i = 0; i < copy_rect.Height(); ++i) { + EXPECT_EQ(0, memcmp(&expected_value[content_row_index], + &results[result_row_index], + copy_rect.Width() * bytes_per_pixel)); + content_row_index += width * bytes_per_pixel; result_row_index += bytes_per_row; } } }; +TEST_F(WebGPUImageBitmapHandlerTest, VerifyColorConvert) { + // All supported CanvasPixelFormat mapping to SkColorType + const SkColorType srcSkColorFormat[] = { + SkColorType::kRGBA_8888_SkColorType, + SkColorType::kBGRA_8888_SkColorType, + SkColorType::kRGBA_F16_SkColorType, + }; + + // Joint of SkColorType and WebGPU texture format + const WGPUTextureFormat kDstWebGPUTextureFormat[] = { + WGPUTextureFormat_RG16Float, WGPUTextureFormat_RGBA16Float, + WGPUTextureFormat_RGBA32Float, + + WGPUTextureFormat_RGB10A2Unorm, WGPUTextureFormat_RG8Unorm, + WGPUTextureFormat_RGBA8Unorm, WGPUTextureFormat_BGRA8Unorm, + WGPUTextureFormat_RGBA8UnormSrgb, WGPUTextureFormat_BGRA8UnormSrgb, + }; + + const CanvasColorSpace kColorSpaces[] = { + CanvasColorSpace::kSRGB, + CanvasColorSpace::kRec2020, + CanvasColorSpace::kP3, + }; + + uint64_t kImageWidth = 3; + uint64_t kImageHeight = 2; + + IntRect image_data_rect(0, 0, kImageWidth, kImageHeight); + + for (SkColorType src_color_type : srcSkColorFormat) { + for (WGPUTextureFormat dst_color_type : kDstWebGPUTextureFormat) { + for (CanvasColorSpace color_space : kColorSpaces) { + CanvasColorParams color_param( + color_space, SkColorTypeToCanvasPixelFormat(src_color_type), + OpacityMode::kNonOpaque); + SkImageInfo info = + SkImageInfo::Make(kImageWidth, kImageHeight, src_color_type, + SkAlphaType::kUnpremul_SkAlphaType, + color_param.GetSkColorSpaceForSkSurfaces()); + VerifyCopyBytes(kImageWidth, kImageHeight, info, color_param, + image_data_rect, dst_color_type, + GetSrcPixelContent(src_color_type), + GetDstContent(dst_color_type)); + } + } + } +} + // Test calculate size TEST_F(WebGPUImageBitmapHandlerTest, VerifyGetWGPUResourceInfo) { - uint64_t imageWidth = 63; - uint64_t imageHeight = 1; + uint64_t kImageWidth = 63; + uint64_t kImageHeight = 1; CanvasColorParams param(CanvasColorSpace::kSRGB, CanvasPixelFormat::kRGBA8, OpacityMode::kNonOpaque); @@ -136,43 +320,62 @@ TEST_F(WebGPUImageBitmapHandlerTest, VerifyGetWGPUResourceInfo) { uint32_t expected_bytes_per_row = 256; uint64_t expected_size = 256; - IntRect test_rect(0, 0, imageWidth, imageHeight); - WebGPUImageUploadSizeInfo info = - ComputeImageBitmapWebGPUUploadSizeInfo(test_rect, param); + IntRect test_rect(0, 0, kImageWidth, kImageHeight); + WebGPUImageUploadSizeInfo info = ComputeImageBitmapWebGPUUploadSizeInfo( + test_rect, WGPUTextureFormat_RGBA8Unorm); ASSERT_EQ(expected_size, info.size_in_bytes); ASSERT_EQ(expected_bytes_per_row, info.wgpu_bytes_per_row); } // Copy full image bitmap test TEST_F(WebGPUImageBitmapHandlerTest, VerifyCopyBytesFromImageBitmapForWebGPU) { - uint64_t imageWidth = 4; - uint64_t imageHeight = 2; + uint64_t kImageWidth = 4; + uint64_t kImageHeight = 2; SkImageInfo info = SkImageInfo::Make( - imageWidth, imageHeight, SkColorType::kRGBA_8888_SkColorType, + kImageWidth, kImageHeight, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType, SkColorSpace::MakeSRGB()); - IntRect image_data_rect(0, 0, imageWidth, imageHeight); + IntRect image_data_rect(0, 0, kImageWidth, kImageHeight); CanvasColorParams color_params(CanvasColorSpace::kSRGB, CanvasPixelFormat::kRGBA8, OpacityMode::kNonOpaque); - VerifyCopyBytesForWebGPU(imageWidth, imageHeight, info, color_params, - image_data_rect); + VerifyCopyBytesForCanvasColorParams(kImageWidth, kImageHeight, info, + color_params, image_data_rect, + WGPUTextureFormat_RGBA8Unorm); } // Copy sub image bitmap test TEST_F(WebGPUImageBitmapHandlerTest, VerifyCopyBytesFromSubImageBitmap) { - uint64_t imageWidth = 63; - uint64_t imageHeight = 4; + uint64_t kImageWidth = 63; + uint64_t kImageHeight = 4; SkImageInfo info = SkImageInfo::Make( - imageWidth, imageHeight, SkColorType::kRGBA_8888_SkColorType, + kImageWidth, kImageHeight, SkColorType::kRGBA_8888_SkColorType, SkAlphaType::kUnpremul_SkAlphaType, SkColorSpace::MakeSRGB()); IntRect image_data_rect(2, 2, 60, 2); CanvasColorParams color_params(CanvasColorSpace::kSRGB, CanvasPixelFormat::kRGBA8, OpacityMode::kNonOpaque); - VerifyCopyBytesForWebGPU(imageWidth, imageHeight, info, color_params, - image_data_rect); + VerifyCopyBytesForCanvasColorParams(kImageWidth, kImageHeight, info, + color_params, image_data_rect, + WGPUTextureFormat_RGBA8Unorm); +} + +// Copy image bitmap with premultiply alpha +TEST_F(WebGPUImageBitmapHandlerTest, VerifyCopyBytesWithPremultiplyAlpha) { + uint64_t kImageWidth = 2; + uint64_t kImageHeight = 1; + SkImageInfo info = SkImageInfo::Make( + kImageWidth, kImageHeight, SkColorType::kRGBA_8888_SkColorType, + SkAlphaType::kPremul_SkAlphaType, SkColorSpace::MakeSRGB()); + + IntRect image_data_rect(0, 0, 2, 1); + CanvasColorParams color_params( + CanvasColorSpace::kSRGB, CanvasPixelFormat::kRGBA8, OpacityMode::kOpaque); + + VerifyCopyBytesForCanvasColorParams(kImageWidth, kImageHeight, info, + color_params, image_data_rect, + WGPUTextureFormat_RGBA8Unorm); } class DawnTextureFromImageBitmapTest : public testing::Test { diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc index 3480e5c9fc3..20dd28f6009 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc @@ -249,7 +249,7 @@ base::TimeDelta XRFrameTransport::WaitForGpuFenceReceived() { return base::TimeTicks::Now() - start; } -void XRFrameTransport::Trace(Visitor* visitor) { +void XRFrameTransport::Trace(Visitor* visitor) const { visitor->Trace(submit_frame_client_receiver_); } diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h index 2ca8d645834..ea42ba83b40 100644 --- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h +++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h @@ -62,7 +62,7 @@ class PLATFORM_EXPORT XRFrameTransport final gpu::gles2::GLES2Interface*, int16_t vr_frame_id); - virtual void Trace(Visitor*); + virtual void Trace(Visitor*) const; private: void WaitForPreviousTransfer(); |