// // Copyright 2019 The ANGLE Project. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // blit.metal: Implements blitting texture content to current frame buffer. #include "common.h" struct BlitParams { // 0: lower left, 1: lower right, 2: upper left float2 srcTexCoords[3]; int srcLevel; bool srcLuminance; // source texture is luminance texture bool dstFlipViewportY; bool dstLuminance; // destination texture is luminance; }; struct BlitVSOut { float4 position [[position]]; float2 texCoords [[user(locn1)]]; }; vertex BlitVSOut blitVS(unsigned int vid [[ vertex_id ]], constant BlitParams &options [[buffer(0)]]) { BlitVSOut output; output.position = float4(gCorners[vid], 0.0, 1.0); output.texCoords = options.srcTexCoords[vid]; if (!options.dstFlipViewportY) { // If viewport is not flipped, we have to flip Y in normalized device coordinates. // Since NDC has Y is opposite direction of viewport coodrinates. output.position.y = -output.position.y; } return output; } float4 blitSampleTexture(texture2d srcTexture, float2 texCoords, constant BlitParams &options) { constexpr sampler textureSampler(mag_filter::linear, min_filter::linear); float4 output = srcTexture.sample(textureSampler, texCoords, level(options.srcLevel)); if (options.srcLuminance) { output.gb = float2(output.r, output.r); } return output; } float4 blitOutput(float4 color, constant BlitParams &options) { float4 ret = color; if (options.dstLuminance) { ret.r = ret.g = ret.b = color.r; } return ret; } fragment float4 blitFS(BlitVSOut input [[stage_in]], texture2d srcTexture [[texture(0)]], constant BlitParams &options [[buffer(0)]]) { return blitOutput(blitSampleTexture(srcTexture, input.texCoords, options), options); } fragment float4 blitPremultiplyAlphaFS(BlitVSOut input [[stage_in]], texture2d srcTexture [[texture(0)]], constant BlitParams &options [[buffer(0)]]) { float4 output = blitSampleTexture(srcTexture, input.texCoords, options); output.xyz *= output.a; return blitOutput(output, options); } fragment float4 blitUnmultiplyAlphaFS(BlitVSOut input [[stage_in]], texture2d srcTexture [[texture(0)]], constant BlitParams &options [[buffer(0)]]) { float4 output = blitSampleTexture(srcTexture, input.texCoords, options); if (output.a != 0.0) { output.xyz *= 1.0 / output.a; } return blitOutput(output, options); }