зеркало из https://github.com/mozilla/gecko-dev.git
168 строки
5.4 KiB
HLSL
168 строки
5.4 KiB
HLSL
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl
|
|
#define mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl
|
|
|
|
#include "common.hlsl"
|
|
|
|
cbuffer VSBufSimple : register(b0)
|
|
{
|
|
float4x4 WorldTransform;
|
|
float2 RenderTargetOffset;
|
|
int SortIndexOffset;
|
|
uint DebugFrameNumber;
|
|
};
|
|
|
|
struct Layer {
|
|
float4x4 transform;
|
|
float4 clipRect;
|
|
uint4 info;
|
|
};
|
|
|
|
cbuffer Layers : register(b1)
|
|
{
|
|
Layer sLayers[682];
|
|
};
|
|
|
|
cbuffer MaskRects : register(b3)
|
|
{
|
|
float4 sMaskRects[4096];
|
|
};
|
|
|
|
struct VertexInfo {
|
|
float4 worldPos;
|
|
float2 screenPos;
|
|
float3 maskCoords;
|
|
float4 clipRect;
|
|
};
|
|
|
|
float3 ComputeMaskCoords(float4 aPosition, Layer aLayer)
|
|
{
|
|
if (aLayer.info.x == 0) {
|
|
return float3(0.0, 0.0, 0.0);
|
|
}
|
|
|
|
float4 maskRect = sMaskRects[aLayer.info.x - 1];
|
|
|
|
// See the perspective comment in CompositorD3D11.hlsl.
|
|
float4x4 transform = float4x4(
|
|
1.0/maskRect.z, 0.0, 0.0, -maskRect.x/maskRect.z,
|
|
0.0, 1.0/maskRect.w, 0.0, -maskRect.y/maskRect.w,
|
|
0.0, 0.0, 1.0, 0.0,
|
|
0.0, 0.0, 0.0, 1.0);
|
|
|
|
return float3(mul(transform, aPosition / aPosition.w).xy, 1.0) * aPosition.w;
|
|
}
|
|
|
|
float2 UnitTriangleToPos(const float3 aVertex,
|
|
const float2 aPos1,
|
|
const float2 aPos2,
|
|
const float2 aPos3)
|
|
{
|
|
return aVertex.x * aPos1 +
|
|
aVertex.y * aPos2 +
|
|
aVertex.z * aPos3;
|
|
}
|
|
|
|
float2 UnitQuadToRect(const float2 aVertex, const float4 aRect)
|
|
{
|
|
return float2(aRect.x + aVertex.x * aRect.z, aRect.y + aVertex.y * aRect.w);
|
|
}
|
|
|
|
float ComputeDepth(float4 aPosition, float aSortIndex)
|
|
{
|
|
// Note: this value should match ShaderDefinitionsMLGPU.h.
|
|
return ((aSortIndex + SortIndexOffset) / 1000000.0f) * aPosition.w;
|
|
}
|
|
|
|
// Compute the world-space, screen-space, layer-space clip, and mask
|
|
// uv-coordinates given a layer-space vertex, id, and z-index.
|
|
VertexInfo ComputePosition(float2 aVertex, uint aLayerId, float aSortIndex)
|
|
{
|
|
Layer layer = sLayers[aLayerId];
|
|
|
|
// Translate from unit vertex to layer quad vertex.
|
|
float4 clipRect = layer.clipRect;
|
|
|
|
// Transform to screen coordinates.
|
|
float4x4 transform = layer.transform;
|
|
float4 layerPos = mul(transform, float4(aVertex, 0, 1));
|
|
float4 position = layerPos;
|
|
position.xyz /= position.w;
|
|
position.xy -= RenderTargetOffset.xy;
|
|
position.xyz *= position.w;
|
|
|
|
float4 worldPos = mul(WorldTransform, position);
|
|
|
|
// Depth must be computed after the world transform, since we don't want
|
|
// 3d transforms clobbering the z-value. We assume a viewport culling
|
|
// everything outside of [0, 1). Note that when depth-testing, we do not
|
|
// use sorting indices < 1.
|
|
//
|
|
// Note that we have to normalize this value to w=1, since the GPU will
|
|
// divide all values by w internally.
|
|
worldPos.z = ComputeDepth(worldPos, aSortIndex);
|
|
|
|
VertexInfo info;
|
|
info.screenPos = position.xy;
|
|
info.worldPos = worldPos;
|
|
info.maskCoords = ComputeMaskCoords(layerPos, layer);
|
|
info.clipRect = clipRect;
|
|
return info;
|
|
}
|
|
|
|
// This function takes a unit quad position and a layer rectangle, and computes
|
|
// a clipped draw rect. It is only valid to use this function for layers with
|
|
// rectilinear transforms that do not have masks.
|
|
float4 ComputeClippedPosition(const float2 aVertex,
|
|
const float4 aRect,
|
|
uint aLayerId,
|
|
float aDepth)
|
|
{
|
|
Layer layer = sLayers[aLayerId];
|
|
|
|
float4 position = float4(UnitQuadToRect(aVertex, aRect), 0, 1);
|
|
|
|
float4x4 transform = layer.transform;
|
|
float4 clipRect = layer.clipRect;
|
|
|
|
// Transform to screen coordinates.
|
|
//
|
|
// We clamp the draw rect to the clip. This lets us use faster shaders.
|
|
// For opaque shapes, it is necessary to do this anyway since we might
|
|
// otherwrite write transparent pixels in the pixel which would also be
|
|
// written to the depth buffer. We cannot use discard in the pixel shader
|
|
// as this would break early-z tests.
|
|
//
|
|
// Note that for some shaders, like textured shaders, it is not valid to
|
|
// change the draw rect like this without also clamping the texture
|
|
// coordinates. We take care to adjust for this in our batching code.
|
|
//
|
|
// We do not need to do this for 3D transforms since we always treat those
|
|
// as transparent (they are not written to the depth buffer). 3D items
|
|
// will always use the full clip+masking shader.
|
|
position = mul(transform, position);
|
|
position.xyz /= position.w;
|
|
position.xy -= RenderTargetOffset.xy;
|
|
position.xy = clamp(position.xy, clipRect.xy, clipRect.xy + clipRect.zw);
|
|
position.xyz *= position.w;
|
|
|
|
float4 worldPos = mul(WorldTransform, position);
|
|
|
|
// Depth must be computed after the world transform, since we don't want
|
|
// 3d transforms clobbering the z-value. We assume a viewport culling
|
|
// everything outside of [0, 1). Note that when depth-testing, we do not
|
|
// use sorting indices < 1.
|
|
//
|
|
// Note that we have to normalize this value to w=1, since the GPU will
|
|
// divide all values by w internally.
|
|
worldPos.z = ComputeDepth(worldPos, aDepth);
|
|
|
|
return worldPos;
|
|
}
|
|
|
|
#endif // mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl
|