1// 2// Copyright 2019 The ANGLE Project. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6// blit.metal: Implements blitting texture content to current frame buffer. 7 8#include "common.h" 9 10 11struct BlitParams 12{ 13 // 0: lower left, 1: lower right, 2: upper left 14 float2 srcTexCoords[3]; 15 int srcLevel; 16 bool srcLuminance; // source texture is luminance texture 17 bool dstFlipViewportY; 18 bool dstLuminance; // destination texture is luminance; 19}; 20 21struct BlitVSOut 22{ 23 float4 position [[position]]; 24 float2 texCoords [[user(locn1)]]; 25}; 26 27vertex BlitVSOut blitVS(unsigned int vid [[ vertex_id ]], 28 constant BlitParams &options [[buffer(0)]]) 29{ 30 BlitVSOut output; 31 output.position = float4(gCorners[vid], 0.0, 1.0); 32 output.texCoords = options.srcTexCoords[vid]; 33 34 if (!options.dstFlipViewportY) 35 { 36 // If viewport is not flipped, we have to flip Y in normalized device coordinates. 37 // Since NDC has Y is opposite direction of viewport coodrinates. 38 output.position.y = -output.position.y; 39 } 40 41 return output; 42} 43 44float4 blitSampleTexture(texture2d<float> srcTexture, 45 float2 texCoords, 46 constant BlitParams &options) 47{ 48 constexpr sampler textureSampler(mag_filter::linear, 49 min_filter::linear); 50 float4 output = srcTexture.sample(textureSampler, texCoords, level(options.srcLevel)); 51 52 if (options.srcLuminance) 53 { 54 output.gb = float2(output.r, output.r); 55 } 56 57 return output; 58} 59 60float4 blitOutput(float4 color, constant BlitParams &options) 61{ 62 float4 ret = color; 63 64 if (options.dstLuminance) 65 { 66 ret.r = ret.g = ret.b = color.r; 67 } 68 69 return ret; 70} 71 72fragment float4 blitFS(BlitVSOut input [[stage_in]], 73 texture2d<float> srcTexture [[texture(0)]], 74 constant BlitParams &options [[buffer(0)]]) 75{ 76 return blitOutput(blitSampleTexture(srcTexture, input.texCoords, options), options); 77} 78 79fragment float4 blitPremultiplyAlphaFS(BlitVSOut input [[stage_in]], 80 texture2d<float> srcTexture [[texture(0)]], 81 constant BlitParams &options [[buffer(0)]]) 82{ 83 float4 output = blitSampleTexture(srcTexture, input.texCoords, options); 84 output.xyz *= output.a; 85 return blitOutput(output, options); 86} 87 88fragment float4 blitUnmultiplyAlphaFS(BlitVSOut input [[stage_in]], 89 texture2d<float> srcTexture [[texture(0)]], 90 constant BlitParams &options [[buffer(0)]]) 91{ 92 float4 output = blitSampleTexture(srcTexture, input.texCoords, options); 93 if (output.a != 0.0) 94 { 95 output.xyz *= 1.0 / output.a; 96 } 97 return blitOutput(output, options); 98} 99