164 lines
6.0 KiB
GLSL
164 lines
6.0 KiB
GLSL
#version 430
|
|
|
|
// pathfinder/shaders/tile.cs.glsl
|
|
//
|
|
// Copyright © 2020 The Pathfinder Project Developers.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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, filterParams3, filterParams4;
|
|
int ctrl;
|
|
computeTileVaryings(fragCoord,
|
|
int(colorEntry),
|
|
uTextureMetadata,
|
|
uTextureMetadataSize,
|
|
colorTexCoord0,
|
|
baseColor,
|
|
filterParams0,
|
|
filterParams1,
|
|
filterParams2,
|
|
filterParams3,
|
|
filterParams4,
|
|
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,
|
|
filterParams3,
|
|
filterParams4,
|
|
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]);
|
|
}
|