2828// This is an example to manually test surface code. Controls are the following, scoped to the
2929// currently focused window:
3030// - W: creates a new window.
31+ // - T: creates a new window with a transparent framebuffer, to test the alpha modes.
3132// - L: Latches the current surface, to check what happens when the window changes but not the
3233// surface.
3334// - R: switches the rendering mode, between "The Red Triangle" and color-cycling clears that's
6465// - Config change tests:
6566// - Check that cycling between present modes.
6667// - Check that cycling between alpha modes (it sometimes produce a meaningful difference).
68+ // - Check alpha modes on a transparent window (T) in the cycling color render mode: the clear
69+ // is premultiplied and cycles its alpha, so Premultiplied and Unpremultiplied let the
70+ // desktop show through and Opaque does not.
6771// - Check that cycling between formats works and gives the same color.
6872//
6973// - Frame throttling:
7579// - Check sRGB vs not sRGB gradients.
7680// - Check wide gamut / extended color range.
7781// - Check OpenGL rendering with extra usages / depth buffer / MRT.
78- // - Check with GLFW transparency on / off.
7982
8083#include < webgpu/webgpu_cpp.h>
8184
@@ -125,6 +128,7 @@ struct WindowData {
125128 uint64_t serial = 0 ;
126129
127130 float clearCycle = 1 .0f ;
131+ bool transparent = false ;
128132 bool latched = false ;
129133 bool renderTriangle = true ;
130134 uint32_t divisor = 1 ;
@@ -200,8 +204,9 @@ void SyncFromWindow(WindowData* data) {
200204 data->targetConfig .height = std::max (1u , static_cast <uint32_t >(height) / data->divisor );
201205}
202206
203- void AddWindow () {
207+ void AddWindow (bool transparent = false ) {
204208 glfwWindowHint (GLFW_CLIENT_API , GLFW_NO_API );
209+ glfwWindowHint (GLFW_TRANSPARENT_FRAMEBUFFER , transparent ? GLFW_TRUE : GLFW_FALSE );
205210 GLFWwindow* window = glfwCreateWindow (400 , 400 , " " , nullptr , nullptr );
206211 glfwSetKeyCallback (window, OnKeyPress);
207212
@@ -221,6 +226,7 @@ void AddWindow() {
221226 std::unique_ptr<WindowData> data = std::make_unique<WindowData>();
222227 data->window = window;
223228 data->serial = windowSerial++;
229+ data->transparent = transparent;
224230 data->surface = surface;
225231 data->currentConfig = config;
226232 data->targetConfig = config;
@@ -257,10 +263,14 @@ void DoRender(WindowData* data) {
257263 data->clearCycle = 1 .0f ;
258264 }
259265
266+ // On a transparent window cycle the alpha as well, so that the alpha modes have a
267+ // visible effect. The color channels are premultiplied so that Premultiplied is valid.
268+ const double alpha = data->transparent ? double {data->clearCycle } : 1.0 ;
269+
260270 dawn::utils::ComboRenderPassDescriptor desc ({view});
261271 desc.cColorAttachments [0 ].loadOp = wgpu::LoadOp::Clear;
262- desc.cColorAttachments [0 ].clearValue = {double {data-> clearCycle },
263- double {1 .0f - data->clearCycle }, 0.0 , 1.0 };
272+ desc.cColorAttachments [0 ].clearValue = {
273+ alpha * double {data-> clearCycle }, alpha * double {1 .0f - data->clearCycle }, 0.0 , alpha };
264274
265275 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass (&desc);
266276 pass.End ();
@@ -316,6 +326,10 @@ void OnKeyPress(GLFWwindow* window, int key, int, int action, int) {
316326 AddWindow ();
317327 break ;
318328
329+ case GLFW_KEY_T :
330+ AddWindow (/* transparent=*/ true );
331+ break ;
332+
319333 case GLFW_KEY_L :
320334 data->latched = !data->latched ;
321335 UpdateTitle (data);
0 commit comments