#version 430 // pathfinder/shaders/tile.cs.glsl // // Copyright © 2020 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #extension GL_GOOGLE_include_directive : enable precision highp float; #ifdef GL_ES precision highp sampler2D; #endif layout(local_size_x = 16, local_size_y = 4) in; #include "tile_fragment.inc.glsl" #include "tile_vertex.inc.glsl" #define LOAD_ACTION_CLEAR 0 #define LOAD_ACTION_LOAD 1 #define TILE_FIELD_NEXT_TILE_ID 0 #define TILE_FIELD_FIRST_FILL_ID 1 #define TILE_FIELD_BACKDROP_ALPHA_TILE_ID 2 #define TILE_FIELD_CONTROL 3 uniform int uLoadAction; uniform vec4 uClearColor; uniform vec2 uTileSize; uniform sampler2D uTextureMetadata; uniform ivec2 uTextureMetadataSize; uniform sampler2D uZBuffer; uniform ivec2 uZBufferSize; uniform sampler2D uColorTexture0; uniform sampler2D uMaskTexture0; uniform sampler2D uGammaLUT; uniform vec2 uColorTextureSize0; uniform vec2 uMaskTextureSize0; uniform vec2 uFramebufferSize; uniform ivec2 uFramebufferTileSize; layout(rgba8) uniform image2D uDestImage; layout(std430, binding = 0) buffer bTiles { // [0]: path ID // [1]: next tile ID // [2]: first fill ID // [3]: backdrop delta upper 8 bits, alpha tile ID lower 24 bits // [4]: color/ctrl/backdrop word restrict readonly uint iTiles[]; }; layout(std430, binding = 1) buffer bFirstTileMap { restrict readonly int iFirstTileMap[]; }; uint calculateTileIndex(uint bufferOffset, uvec4 tileRect, uvec2 tileCoord) { return bufferOffset + tileCoord.y * (tileRect.z - tileRect.x) + tileCoord.x; } ivec2 toImageCoords(ivec2 coords) { return ivec2(coords.x, uFramebufferSize.y - coords.y); } void main() { ivec2 tileCoord = ivec2(gl_WorkGroupID.xy); ivec2 firstTileSubCoord = ivec2(gl_LocalInvocationID.xy) * ivec2(1, 4); ivec2 firstFragCoord = tileCoord * ivec2(uTileSize) + firstTileSubCoord; // Quick exit if this is guaranteed to be empty. int tileIndex = iFirstTileMap[tileCoord.x + uFramebufferTileSize.x * tileCoord.y]; if (tileIndex < 0 && uLoadAction != LOAD_ACTION_CLEAR) return; mat4 destColors; for (int subY = 0; subY < 4; subY++) { if (uLoadAction == LOAD_ACTION_CLEAR) { destColors[subY] = uClearColor; } else { ivec2 imageCoords = toImageCoords(firstFragCoord + ivec2(0, subY)); destColors[subY] = imageLoad(uDestImage, imageCoords); } } while (tileIndex >= 0) { for (int subY = 0; subY < 4; subY++) { ivec2 tileSubCoord = firstTileSubCoord + ivec2(0, subY); vec2 fragCoord = vec2(firstFragCoord + ivec2(0, subY)) + vec2(0.5); int alphaTileIndex = int(iTiles[tileIndex * 4 + TILE_FIELD_BACKDROP_ALPHA_TILE_ID] << 8) >> 8; uint tileControlWord = iTiles[tileIndex * 4 + TILE_FIELD_CONTROL]; uint colorEntry = tileControlWord & 0xffff; int tileCtrl = int((tileControlWord >> 16) & 0xff); int backdrop; uvec2 maskTileCoord; if (alphaTileIndex >= 0) { backdrop = 0; maskTileCoord = uvec2(alphaTileIndex & 0xff, alphaTileIndex >> 8) * uvec2(uTileSize); } else { // We have no alpha mask. Clear the mask bits so we don't try to look one up. backdrop = int(tileControlWord) >> 24; maskTileCoord = uvec2(0u); tileCtrl &= ~(TILE_CTRL_MASK_MASK << TILE_CTRL_MASK_0_SHIFT); } vec3 maskTexCoord0 = vec3(vec2(ivec2(maskTileCoord) + tileSubCoord), backdrop); vec2 colorTexCoord0; vec4 baseColor, filterParams0, filterParams1, filterParams2; int ctrl; computeTileVaryings(fragCoord, int(colorEntry), uTextureMetadata, uTextureMetadataSize, colorTexCoord0, baseColor, filterParams0, filterParams1, filterParams2, ctrl); // FIXME(pcwalton): The `uColorTexture0` below is a placeholder and needs to be // replaced! vec4 srcColor = calculateColor(fragCoord, uColorTexture0, uMaskTexture0, uColorTexture0, uGammaLUT, uColorTextureSize0, uMaskTextureSize0, filterParams0, filterParams1, filterParams2, uFramebufferSize, ctrl, maskTexCoord0, colorTexCoord0, baseColor, tileCtrl); destColors[subY] = destColors[subY] * (1.0 - srcColor.a) + srcColor; } tileIndex = int(iTiles[tileIndex * 4 + TILE_FIELD_NEXT_TILE_ID]); } for (int subY = 0; subY < 4; subY++) imageStore(uDestImage, toImageCoords(firstFragCoord + ivec2(0, subY)), destColors[subY]); }