Add clear alpha to one step to copy texture for browser

Bug: chromium:1331139
Change-Id: I69c31aea0320f302be686adf0167649a98db3414
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/95682
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Shaobo Yan <shaobo.yan@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
shrekshao 2022-07-11 18:11:14 +00:00 committed by Shrek Shao
parent c6cbcdb05b
commit a3f4a32022
3 changed files with 54 additions and 40 deletions

View File

@ -904,7 +904,8 @@
"tags": ["dawn"], "tags": ["dawn"],
"values": [ "values": [
{"value": 0, "name": "premultiplied"}, {"value": 0, "name": "premultiplied"},
{"value": 1, "name": "unpremultiplied"} {"value": 1, "name": "unpremultiplied"},
{"value": 2, "name": "opaque"}
] ]
}, },
"copy texture for browser options": { "copy texture for browser options": {

View File

@ -145,9 +145,11 @@ static const char sCopyTextureForBrowserShader[] = R"(
let kEncodeToGammaStep = 0x08u; let kEncodeToGammaStep = 0x08u;
let kPremultiplyStep = 0x10u; let kPremultiplyStep = 0x10u;
let kDecodeForSrgbDstFormat = 0x20u; let kDecodeForSrgbDstFormat = 0x20u;
let kClearSrcAlphaToOne = 0x40u;
// Unpremultiply step. Appling color space conversion op on premultiplied source texture // Unpremultiply step. Appling color space conversion op on premultiplied source texture
// also needs to unpremultiply first. // also needs to unpremultiply first.
// This step is exclusive with clear src alpha to one step.
if (bool(uniforms.steps_mask & kUnpremultiplyStep)) { if (bool(uniforms.steps_mask & kUnpremultiplyStep)) {
if (color.a != 0.0) { if (color.a != 0.0) {
color = vec4<f32>(color.rgb / color.a, color.a); color = vec4<f32>(color.rgb / color.a, color.a);
@ -180,6 +182,7 @@ static const char sCopyTextureForBrowserShader[] = R"(
} }
// Premultiply step. // Premultiply step.
// This step is exclusive with clear src alpha to one step.
if (bool(uniforms.steps_mask & kPremultiplyStep)) { if (bool(uniforms.steps_mask & kPremultiplyStep)) {
color = vec4<f32>(color.rgb * color.a, color.a); color = vec4<f32>(color.rgb * color.a, color.a);
} }
@ -192,6 +195,12 @@ static const char sCopyTextureForBrowserShader[] = R"(
color.a); color.a);
} }
// Clear alpha to one step.
// This step is exclusive with premultiply/unpremultiply step.
if (bool(uniforms.steps_mask & kClearSrcAlphaToOne)) {
color.a = 1.0;
}
return color; return color;
} }
)"; )";
@ -456,11 +465,16 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
constexpr uint32_t kEncodeToGammaStep = 0x08; constexpr uint32_t kEncodeToGammaStep = 0x08;
constexpr uint32_t kPremultiplyStep = 0x10; constexpr uint32_t kPremultiplyStep = 0x10;
constexpr uint32_t kDecodeForSrgbDstFormat = 0x20; constexpr uint32_t kDecodeForSrgbDstFormat = 0x20;
constexpr uint32_t kClearSrcAlphaToOne = 0x40;
if (options->srcAlphaMode == wgpu::AlphaMode::Premultiplied) { if (options->srcAlphaMode == wgpu::AlphaMode::Premultiplied) {
if (options->needsColorSpaceConversion || options->srcAlphaMode != options->dstAlphaMode) { if (options->needsColorSpaceConversion ||
options->dstAlphaMode == wgpu::AlphaMode::Unpremultiplied) {
stepsMask |= kUnpremultiplyStep; stepsMask |= kUnpremultiplyStep;
} }
} else if (options->srcAlphaMode == wgpu::AlphaMode::Opaque) {
// Simply clear src alpha channel to 1.0
stepsMask |= kClearSrcAlphaToOne;
} }
if (options->needsColorSpaceConversion) { if (options->needsColorSpaceConversion) {
@ -497,7 +511,8 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
} }
if (options->dstAlphaMode == wgpu::AlphaMode::Premultiplied) { if (options->dstAlphaMode == wgpu::AlphaMode::Premultiplied) {
if (options->needsColorSpaceConversion || options->srcAlphaMode != options->dstAlphaMode) { if (options->needsColorSpaceConversion ||
options->srcAlphaMode == wgpu::AlphaMode::Unpremultiplied) {
stepsMask |= kPremultiplyStep; stepsMask |= kPremultiplyStep;
} }
} }
@ -587,7 +602,7 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
renderPassDesc.colorAttachments = &colorAttachmentDesc; renderPassDesc.colorAttachments = &colorAttachmentDesc;
Ref<RenderPassEncoder> passEncoder = encoder->BeginRenderPass(&renderPassDesc); Ref<RenderPassEncoder> passEncoder = encoder->BeginRenderPass(&renderPassDesc);
// Start pipeline and encode commands to complete // Start pipeline and encode commands to complete
// the copy from src texture to dst texture with transformation. // the copy from src texture to dst texture with transformation.
passEncoder->APISetPipeline(pipeline); passEncoder->APISetPipeline(pipeline);
passEncoder->APISetBindGroup(0, bindGroup.Get()); passEncoder->APISetBindGroup(0, bindGroup.Get());

View File

@ -181,25 +181,22 @@ class CopyTextureForBrowserTests : public Parent {
// Source textures will have variable pixel data to cover cases like // Source textures will have variable pixel data to cover cases like
// flipY. // flipY.
if (textureRole == TextureCopyRole::SOURCE) { if (textureRole == TextureCopyRole::SOURCE) {
if (srcAlphaMode != dstAlphaMode) { if (srcAlphaMode == wgpu::AlphaMode::Unpremultiplied &&
if (dstAlphaMode == wgpu::AlphaMode::Premultiplied) { dstAlphaMode == wgpu::AlphaMode::Premultiplied) {
// For premultiply alpha test cases, we expect each channel in dst // We expect each channel in dst
// texture will equal to the alpha channel value. // texture will equal to the alpha channel value.
ASSERT(srcAlphaMode == wgpu::AlphaMode::Unpremultiplied); textureData[sliceOffset + rowOffset + x] = RGBA8(
textureData[sliceOffset + rowOffset + x] = RGBA8( static_cast<uint8_t>(255), static_cast<uint8_t>(255),
static_cast<uint8_t>(255), static_cast<uint8_t>(255), static_cast<uint8_t>(255), static_cast<uint8_t>(alpha[x % 4]));
static_cast<uint8_t>(255), static_cast<uint8_t>(alpha[x % 4])); } else if (srcAlphaMode == wgpu::AlphaMode::Premultiplied &&
} else { dstAlphaMode == wgpu::AlphaMode::Unpremultiplied) {
// For unpremultiply alpha test cases, we expect each channel in dst // We expect each channel in dst
// texture will equal to 1.0. // texture will equal to 1.0.
ASSERT(srcAlphaMode == wgpu::AlphaMode::Premultiplied); textureData[sliceOffset + rowOffset + x] =
textureData[sliceOffset + rowOffset + x] = RGBA8(static_cast<uint8_t>(alpha[x % 4]),
RGBA8(static_cast<uint8_t>(alpha[x % 4]), static_cast<uint8_t>(alpha[x % 4]),
static_cast<uint8_t>(alpha[x % 4]), static_cast<uint8_t>(alpha[x % 4]),
static_cast<uint8_t>(alpha[x % 4]), static_cast<uint8_t>(alpha[x % 4]));
static_cast<uint8_t>(alpha[x % 4]));
}
} else { } else {
textureData[sliceOffset + rowOffset + x] = textureData[sliceOffset + rowOffset + x] =
RGBA8(static_cast<uint8_t>((x + layer * x) % 256), RGBA8(static_cast<uint8_t>((x + layer * x) % 256),
@ -300,17 +297,18 @@ class CopyTextureForBrowserTests : public Parent {
// after premultiply. // after premultiply.
let premultiplied = 0u; let premultiplied = 0u;
let unpremultiplied = 1u; let unpremultiplied = 1u;
if (uniforms.srcAlphaMode != uniforms.dstAlphaMode) { let opaque = 2u;
if (uniforms.dstAlphaMode == premultiplied) { if (uniforms.srcAlphaMode == opaque) {
// srcAlphaMode == unpremultiplied srcColor.a = 1.0;
srcColor = vec4<f32>(srcColor.rgb * srcColor.a, srcColor.a); }
}
if (uniforms.dstAlphaMode == unpremultiplied) { if (uniforms.srcAlphaMode == unpremultiplied && uniforms.dstAlphaMode == premultiplied) {
// srcAlphaMode == premultiplied srcColor = vec4<f32>(srcColor.rgb * srcColor.a, srcColor.a);
if (srcColor.a != 0.0) { }
srcColor = vec4<f32>(srcColor.rgb / srcColor.a, srcColor.a);
} if (uniforms.srcAlphaMode == premultiplied && uniforms.dstAlphaMode == unpremultiplied) {
if (srcColor.a != 0.0) {
srcColor = vec4<f32>(srcColor.rgb / srcColor.a, srcColor.a);
} }
} }
@ -1134,13 +1132,13 @@ TEST_P(CopyTextureForBrowser_AlphaMode, alphaMode) {
DoAlphaModeTest(); DoAlphaModeTest();
} }
DAWN_INSTANTIATE_TEST_P(CopyTextureForBrowser_AlphaMode, DAWN_INSTANTIATE_TEST_P(
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), CopyTextureForBrowser_AlphaMode,
VulkanBackend()}, {D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()},
std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied, std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied, wgpu::AlphaMode::Unpremultiplied,
wgpu::AlphaMode::Unpremultiplied}), wgpu::AlphaMode::Opaque}),
std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied, std::vector<wgpu::AlphaMode>({wgpu::AlphaMode::Premultiplied, wgpu::AlphaMode::Unpremultiplied,
wgpu::AlphaMode::Unpremultiplied})); wgpu::AlphaMode::Opaque}));
// Verify |CopyTextureForBrowser| doing color space conversion. // Verify |CopyTextureForBrowser| doing color space conversion.
TEST_P(CopyTextureForBrowser_ColorSpace, colorSpaceConversion) { TEST_P(CopyTextureForBrowser_ColorSpace, colorSpaceConversion) {