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