/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // Composite a picture cache tile into the framebuffer. // This shader must remain compatible with ESSL 1, at least for the // WR_FEATURE_TEXTURE_EXTERNAL_ESSL1 feature, so that it can be used to render // video on GLES devices without GL_OES_EGL_image_external_essl3 support. // This means we cannot use textureSize(), int inputs/outputs, etc. #include shared #ifdef WR_FEATURE_YUV #include yuv #endif #ifdef WR_FEATURE_YUV flat varying YUV_PRECISION vec3 vYcbcrBias; flat varying YUV_PRECISION mat3 vRgbFromDebiasedYcbcr; // YUV format. Packed in to vector to avoid bug 1630356. flat varying mediump ivec2 vYuvFormat; #ifdef SWGL_DRAW_SPAN flat varying mediump int vRescaleFactor; #endif varying highp vec2 vUV_y; varying highp vec2 vUV_u; varying highp vec2 vUV_v; flat varying highp vec4 vUVBounds_y; flat varying highp vec4 vUVBounds_u; flat varying highp vec4 vUVBounds_v; #else varying highp vec2 vUv; #ifndef WR_FEATURE_FAST_PATH flat varying mediump vec4 vColor; flat varying highp vec4 vUVBounds; #endif #ifdef WR_FEATURE_TEXTURE_EXTERNAL_ESSL1 uniform mediump vec2 uTextureSize; #endif #endif #ifdef WR_VERTEX_SHADER // CPU side data is in CompositeInstance (gpu_types.rs) and is // converted to GPU data using desc::COMPOSITE (renderer.rs) by // filling vaos.composite_vao with VertexArrayKind::Composite. PER_INSTANCE attribute vec4 aLocalRect; PER_INSTANCE attribute vec4 aDeviceClipRect; PER_INSTANCE attribute vec4 aColor; PER_INSTANCE attribute vec4 aParams; PER_INSTANCE attribute vec4 aTransform; #ifdef WR_FEATURE_YUV // YUV treats these as a UV clip rect (clamp) PER_INSTANCE attribute vec4 aUvRect0; PER_INSTANCE attribute vec4 aUvRect1; PER_INSTANCE attribute vec4 aUvRect2; #else PER_INSTANCE attribute vec4 aUvRect0; #endif vec2 apply_transform(vec2 p, vec4 transform) { return p * transform.xy + transform.zw; } #ifdef WR_FEATURE_YUV YuvPrimitive fetch_yuv_primitive() { // From ExternalSurfaceDependency::Yuv: int color_space = int(aParams.y); int yuv_format = int(aParams.z); int channel_bit_depth = int(aParams.w); return YuvPrimitive(channel_bit_depth, color_space, yuv_format); } #endif void main(void) { // Get world position vec2 world_p0 = apply_transform(aLocalRect.xy, aTransform); vec2 world_p1 = apply_transform(aLocalRect.zw, aTransform); vec2 world_pos = mix(world_p0, world_p1, aPosition.xy); // Clip the position to the world space clip rect vec2 clipped_world_pos = clamp(world_pos, aDeviceClipRect.xy, aDeviceClipRect.zw); // Derive the normalized UV from the clipped vertex position vec2 uv = (clipped_world_pos - world_p0) / (world_p1 - world_p0); #ifdef WR_FEATURE_YUV YuvPrimitive prim = fetch_yuv_primitive(); #ifdef SWGL_DRAW_SPAN // swgl_commitTextureLinearYUV needs to know the color space specifier and // also needs to know how many bits of scaling are required to normalize // HDR textures. Note that MSB HDR formats don't need renormalization. vRescaleFactor = 0; if (prim.channel_bit_depth > 8 && prim.yuv_format != YUV_FORMAT_P010) { vRescaleFactor = 16 - prim.channel_bit_depth; } #endif YuvColorMatrixInfo mat_info = get_rgb_from_ycbcr_info(prim); vYcbcrBias = mat_info.ycbcr_bias; vRgbFromDebiasedYcbcr = mat_info.rgb_from_debiased_ycbrc; vYuvFormat.x = prim.yuv_format; write_uv_rect( aUvRect0.xy, aUvRect0.zw, uv, TEX_SIZE_YUV(sColor0), vUV_y, vUVBounds_y ); write_uv_rect( aUvRect1.xy, aUvRect1.zw, uv, TEX_SIZE_YUV(sColor1), vUV_u, vUVBounds_u ); write_uv_rect( aUvRect2.xy, aUvRect2.zw, uv, TEX_SIZE_YUV(sColor2), vUV_v, vUVBounds_v ); #else uv = mix(aUvRect0.xy, aUvRect0.zw, uv); // The uvs may be inverted, so use the min and max for the bounds vec4 uvBounds = vec4(min(aUvRect0.xy, aUvRect0.zw), max(aUvRect0.xy, aUvRect0.zw)); int rescale_uv = int(aParams.y); if (rescale_uv == 1) { // using an atlas, so UVs are in pixels, and need to be // normalized and clamped. #if defined(WR_FEATURE_TEXTURE_RECT) vec2 texture_size = vec2(1.0, 1.0); #elif defined(WR_FEATURE_TEXTURE_EXTERNAL_ESSL1) vec2 texture_size = uTextureSize; #else vec2 texture_size = vec2(TEX_SIZE(sColor0)); #endif uvBounds += vec4(0.5, 0.5, -0.5, -0.5); #ifndef WR_FEATURE_TEXTURE_RECT uv /= texture_size; uvBounds /= texture_size.xyxy; #endif } vUv = uv; #ifndef WR_FEATURE_FAST_PATH vUVBounds = uvBounds; // Pass through color vColor = aColor; #endif #endif gl_Position = uTransform * vec4(clipped_world_pos, 0.0, 1.0); } #endif #ifdef WR_FRAGMENT_SHADER void main(void) { #ifdef WR_FEATURE_YUV vec4 color = sample_yuv( vYuvFormat.x, vYcbcrBias, vRgbFromDebiasedYcbcr, vUV_y, vUV_u, vUV_v, vUVBounds_y, vUVBounds_u, vUVBounds_v ); #else // The color is just the texture sample modulated by a supplied color. // In the fast path we avoid clamping the UV coordinates and modulating by the color. #ifdef WR_FEATURE_FAST_PATH vec2 uv = vUv; #else vec2 uv = clamp(vUv, vUVBounds.xy, vUVBounds.zw); #endif vec4 texel = TEX_SAMPLE(sColor0, uv); #ifdef WR_FEATURE_FAST_PATH vec4 color = texel; #else vec4 color = vColor * texel; #endif #endif write_output(color); } #ifdef SWGL_DRAW_SPAN void swgl_drawSpanRGBA8() { #ifdef WR_FEATURE_YUV if (vYuvFormat.x == YUV_FORMAT_PLANAR) { swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, sColor1, vUV_u, vUVBounds_u, sColor2, vUV_v, vUVBounds_v, vYcbcrBias, vRgbFromDebiasedYcbcr, vRescaleFactor); } else if (vYuvFormat.x == YUV_FORMAT_NV12 || vYuvFormat.x == YUV_FORMAT_P010) { swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, sColor1, vUV_u, vUVBounds_u, vYcbcrBias, vRgbFromDebiasedYcbcr, vRescaleFactor); } else if (vYuvFormat.x == YUV_FORMAT_INTERLEAVED) { swgl_commitTextureLinearYUV(sColor0, vUV_y, vUVBounds_y, vYcbcrBias, vRgbFromDebiasedYcbcr, vRescaleFactor); } #else #ifdef WR_FEATURE_FAST_PATH vec4 color = vec4(1.0); #ifdef WR_FEATURE_TEXTURE_RECT vec4 uvBounds = vec4(vec2(0.0), vec2(textureSize(sColor0))); #else vec4 uvBounds = vec4(0.0, 0.0, 1.0, 1.0); #endif #else vec4 color = vColor; vec4 uvBounds = vUVBounds; #endif if (color != vec4(1.0)) { swgl_commitTextureColorRGBA8(sColor0, vUv, uvBounds, color); } else { swgl_commitTextureRGBA8(sColor0, vUv, uvBounds); } #endif } #endif #endif