1/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6#ifndef mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl 7#define mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl 8 9#include "common.hlsl" 10 11cbuffer VSBufSimple : register(b0) 12{ 13 float4x4 WorldTransform; 14 float2 RenderTargetOffset; 15 int SortIndexOffset; 16 uint DebugFrameNumber; 17}; 18 19struct Layer { 20 float4x4 transform; 21 float4 clipRect; 22 uint4 info; 23}; 24 25cbuffer Layers : register(b1) 26{ 27 Layer sLayers[682]; 28}; 29 30cbuffer MaskRects : register(b3) 31{ 32 float4 sMaskRects[4096]; 33}; 34 35struct VertexInfo { 36 float4 worldPos; 37 float2 screenPos; 38 float3 maskCoords; 39 float4 clipRect; 40}; 41 42float3 ComputeMaskCoords(float4 aPosition, Layer aLayer) 43{ 44 if (aLayer.info.x == 0) { 45 return float3(0.0, 0.0, 0.0); 46 } 47 48 float4 maskRect = sMaskRects[aLayer.info.x - 1]; 49 50 // See the perspective comment in CompositorD3D11.hlsl. 51 float4x4 transform = float4x4( 52 1.0/maskRect.z, 0.0, 0.0, -maskRect.x/maskRect.z, 53 0.0, 1.0/maskRect.w, 0.0, -maskRect.y/maskRect.w, 54 0.0, 0.0, 1.0, 0.0, 55 0.0, 0.0, 0.0, 1.0); 56 57 return float3(mul(transform, aPosition / aPosition.w).xy, 1.0) * aPosition.w; 58} 59 60float2 UnitTriangleToPos(const float3 aVertex, 61 const float2 aPos1, 62 const float2 aPos2, 63 const float2 aPos3) 64{ 65 return aVertex.x * aPos1 + 66 aVertex.y * aPos2 + 67 aVertex.z * aPos3; 68} 69 70float2 UnitQuadToRect(const float2 aVertex, const float4 aRect) 71{ 72 return float2(aRect.x + aVertex.x * aRect.z, aRect.y + aVertex.y * aRect.w); 73} 74 75float ComputeDepth(float4 aPosition, float aSortIndex) 76{ 77 // Note: this value should match ShaderDefinitionsMLGPU.h. 78 return ((aSortIndex + SortIndexOffset) / 1000000.0f) * aPosition.w; 79} 80 81// Compute the world-space, screen-space, layer-space clip, and mask 82// uv-coordinates given a layer-space vertex, id, and z-index. 83VertexInfo ComputePosition(float2 aVertex, uint aLayerId, float aSortIndex) 84{ 85 Layer layer = sLayers[aLayerId]; 86 87 // Translate from unit vertex to layer quad vertex. 88 float4 clipRect = layer.clipRect; 89 90 // Transform to screen coordinates. 91 float4x4 transform = layer.transform; 92 float4 layerPos = mul(transform, float4(aVertex, 0, 1)); 93 float4 position = layerPos; 94 position.xyz /= position.w; 95 position.xy -= RenderTargetOffset.xy; 96 position.xyz *= position.w; 97 98 float4 worldPos = mul(WorldTransform, position); 99 100 // Depth must be computed after the world transform, since we don't want 101 // 3d transforms clobbering the z-value. We assume a viewport culling 102 // everything outside of [0, 1). Note that when depth-testing, we do not 103 // use sorting indices < 1. 104 // 105 // Note that we have to normalize this value to w=1, since the GPU will 106 // divide all values by w internally. 107 worldPos.z = ComputeDepth(worldPos, aSortIndex); 108 109 VertexInfo info; 110 info.screenPos = position.xy; 111 info.worldPos = worldPos; 112 info.maskCoords = ComputeMaskCoords(layerPos, layer); 113 info.clipRect = clipRect; 114 return info; 115} 116 117// This function takes a unit quad position and a layer rectangle, and computes 118// a clipped draw rect. It is only valid to use this function for layers with 119// rectilinear transforms that do not have masks. 120float4 ComputeClippedPosition(const float2 aVertex, 121 const float4 aRect, 122 uint aLayerId, 123 float aDepth) 124{ 125 Layer layer = sLayers[aLayerId]; 126 127 float4 position = float4(UnitQuadToRect(aVertex, aRect), 0, 1); 128 129 float4x4 transform = layer.transform; 130 float4 clipRect = layer.clipRect; 131 132 // Transform to screen coordinates. 133 // 134 // We clamp the draw rect to the clip. This lets us use faster shaders. 135 // For opaque shapes, it is necessary to do this anyway since we might 136 // otherwrite write transparent pixels in the pixel which would also be 137 // written to the depth buffer. We cannot use discard in the pixel shader 138 // as this would break early-z tests. 139 // 140 // Note that for some shaders, like textured shaders, it is not valid to 141 // change the draw rect like this without also clamping the texture 142 // coordinates. We take care to adjust for this in our batching code. 143 // 144 // We do not need to do this for 3D transforms since we always treat those 145 // as transparent (they are not written to the depth buffer). 3D items 146 // will always use the full clip+masking shader. 147 position = mul(transform, position); 148 position.xyz /= position.w; 149 position.xy -= RenderTargetOffset.xy; 150 position.xy = clamp(position.xy, clipRect.xy, clipRect.xy + clipRect.zw); 151 position.xyz *= position.w; 152 153 float4 worldPos = mul(WorldTransform, position); 154 155 // Depth must be computed after the world transform, since we don't want 156 // 3d transforms clobbering the z-value. We assume a viewport culling 157 // everything outside of [0, 1). Note that when depth-testing, we do not 158 // use sorting indices < 1. 159 // 160 // Note that we have to normalize this value to w=1, since the GPU will 161 // divide all values by w internally. 162 worldPos.z = ComputeDepth(worldPos, aDepth); 163 164 return worldPos; 165} 166 167#endif // mozilla_gfx_layers_d3d11_mlgshaders_common_vs_hlsl 168