ler: sampler; // Resource used in copyTexture entry point only. @binding(2) @group(0) var mySourceTexture: texture_2d; // Resource used in copyExternalTexture entry point only. @binding(2) @group(0) var mySourceExternalTexture: texture_external; fn discardIfOutsideOfCopy(texcoord : vec2f) { var clampedTexcoord = clamp(texcoord, vec2f(0.0, 0.0), vec2f(1.0, 1.0)); if (!all(clampedTexcoord == texcoord)) { discard; } } fn transform(srcColor : vec4f) -> vec4f { var color = srcColor; let kUnpremultiplyStep = 0x01u; let kDecodeToLinearStep = 0x02u; let kConvertToDstGamutStep = 0x04u; let kEncodeToGammaStep = 0x08u; let kPremultiplyStep = 0x10u; let kDecodeForSrgbDstFormat = 0x20u; let kClearSrcAlphaToOne = 0x40u; // Unpremultiply step. Appling color space conversion op on premultiplied source texture // also needs to unpremultiply first. // This step is exclusive with clear src alpha to one step. if (bool(uniforms.steps_mask & kUnpremultiplyStep)) { if (color.a != 0.0) { color = vec4f(color.rgb / color.a, color.a); } } // Linearize the source color using the source color space’s // transfer function if it is non-linear. if (bool(uniforms.steps_mask & kDecodeToLinearStep)) { color = vec4f(gamma_conversion(color.r, uniforms.gamma_decoding_params), gamma_conversion(color.g, uniforms.gamma_decoding_params), gamma_conversion(color.b, uniforms.gamma_decoding_params), color.a); } // Convert unpremultiplied, linear source colors to the destination gamut by // multiplying by a 3x3 matrix. Calculate transformFromXYZD50 * transformToXYZD50 // in CPU side and upload the final result in uniforms. if (bool(uniforms.steps_mask & kConvertToDstGamutStep)) { color = vec4f(uniforms.conversion_matrix * color.rgb, color.a); } // Encode that color using the inverse of the destination color // space’s transfer function if it is non-linear. if (bool(uniforms.steps_mask & kEncodeToGammaStep)) { color = vec4f(gamma_conversion(color.r, uniforms.gamma_encoding_params), gamma_conversion(color.g, uniforms.gamma_encoding_params), gamma_conversion(color.b, uniforms.gamma_encoding_params), color.a); } // Premultiply step. // This step is exclusive with clear src alpha to one step. if (bool(uniforms.steps_mask & kPremultiplyStep)) { color = vec4f(color.rgb * color.a, color.a); } // Decode for copying from non-srgb formats to srgb formats if (bool(uniforms.steps_mask & kDecodeForSrgbDstFormat)) { color = vec4f(gamma_conversion(color.r, uniforms.gamma_decoding_for_dst_srgb_params), gamma_conversion(color.g, uniforms.gamma_decoding_for_dst_srgb_params), gamma_conversion(color.b, uniforms.gamma_decoding_for_dst_srgb_params), 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; } @fragment fn copyTexture(@location(0) texcoord : vec2f ) -> @location(0) vec4f { discardIfOutsideOfCopy(texcoord); var color = textureSample(mySourceTexture, mySampler, texcoord); return transform(color); } @fragment fn copyExternalTexture(@location(0) texcoord : vec2f ) -> @location(0) vec4f { discardIfOutsideOfCopy(texcoord); var color = textureSampleBaseClampToEdge(mySourceExternalTexture, mySampler, texcoord); return transform(color); }