blob: 330927822eb5520b9be5e933965d1ada8cec38ad [file] [log] [blame]
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ImageCopy.frag: Copy parts of an image to another.
#version 450 core
#extension GL_EXT_samplerless_texture_functions : require
#define MAKE_SRC_RESOURCE(prefix, type) prefix ## type
#if SrcIsFloat
#define SRC_RESOURCE(type) type
#define SrcType vec4
#elif SrcIsSint
#define SRC_RESOURCE(type) MAKE_SRC_RESOURCE(i, type)
#define SrcType ivec4
#elif SrcIsUint
#define SRC_RESOURCE(type) MAKE_SRC_RESOURCE(u, type)
#define SrcType uvec4
#else
#error "Not all source formats are accounted for"
#endif
#if SrcIsArray
#define SRC_RESOURCE_NAME texture2DArray
#else
#define SRC_RESOURCE_NAME texture2D
#endif
#if DestIsFloat
#define DestType vec4
#elif DestIsSint
#define DestType ivec4
#elif DestIsUint
#define DestType uvec4
#else
#error "Not all destination formats are accounted for"
#endif
layout(set = 0, binding = 0) uniform SRC_RESOURCE(SRC_RESOURCE_NAME) src;
layout(location = 0) out DestType dest;
layout(push_constant) uniform PushConstants {
// Translation from source to destination coordinates.
ivec2 srcOffset;
ivec2 destOffset;
int srcMip;
int srcLayer;
// Whether y needs to be flipped
bool flipY;
// Premultiplied alpha conversions
bool premultiplyAlpha;
bool unmultiplyAlpha;
// Whether destination is emulated luminance/alpha.
bool destHasLuminance;
bool destIsAlpha;
// Bits 0~3 tell whether R,G,B or A exist in destination, but as a result of format emulation.
// Bit 0 is ignored, because R is always present. For B and G, the result is set to 0 and for
// A, the result is set to 1.
int destDefaultChannelsMask;
} params;
void main()
{
ivec2 destSubImageCoords = ivec2(gl_FragCoord.xy) - params.destOffset;
ivec2 srcSubImageCoords = destSubImageCoords;
// If flipping Y, srcOffset would contain the opposite y coordinate, so we can
// simply reverse the direction in which y grows.
if (params.flipY)
srcSubImageCoords.y = -srcSubImageCoords.y;
#if SrcIsArray
SrcType srcValue = texelFetch(src, ivec3(params.srcOffset + srcSubImageCoords, params.srcLayer), params.srcMip);
#else
SrcType srcValue = texelFetch(src, params.srcOffset + srcSubImageCoords, params.srcMip);
#endif
if (params.premultiplyAlpha)
{
srcValue.rgb *= srcValue.a;
}
else if (params.unmultiplyAlpha && srcValue.a > 0)
{
srcValue.rgb /= srcValue.a;
}
// Convert value to destination type.
DestType destValue = DestType(srcValue);
// If dest is luminance/alpha, it's implemented with R or RG. Do the appropriate swizzle.
if (params.destHasLuminance)
{
destValue.rg = destValue.ra;
}
else if (params.destIsAlpha)
{
destValue.r = destValue.a;
}
else
{
int defaultChannelsMask = params.destDefaultChannelsMask;
if ((defaultChannelsMask & 2) != 0)
{
destValue.g = 0;
}
if ((defaultChannelsMask & 4) != 0)
{
destValue.b = 0;
}
if ((defaultChannelsMask & 8) != 0)
{
destValue.a = 1;
}
}
dest = destValue;
}