blob: c6744eeb576e525aa68f266582534e0a7675c936 [file] [log] [blame]
//
// 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, 3: upper right
float2 srcTexCoords[4];
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[gTexcoordsIndices[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<float> 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<float> srcTexture [[texture(0)]],
constant BlitParams &options [[buffer(0)]])
{
return blitOutput(blitSampleTexture(srcTexture, input.texCoords, options), options);
}
fragment float4 blitPremultiplyAlphaFS(BlitVSOut input [[stage_in]],
texture2d<float> 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<float> 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);
}