azul_webrender/renderer/
vertex.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//! Rendering logic related to the vertex shaders and their states, uncluding
6//!  - Vertex Array Objects
7//!  - vertex layout descriptors
8//!  - textures bound at vertex stage
9
10use std::{marker::PhantomData, mem, num::NonZeroUsize, ops};
11use api::units::*;
12use crate::{
13    device::{
14        Device, Texture, TextureFilter, TextureUploader, UploadPBOPool, VertexUsageHint, VAO,
15    },
16    frame_builder::Frame,
17    gpu_types::{PrimitiveHeaderI, PrimitiveHeaderF, TransformData},
18    internal_types::Swizzle,
19    render_task::RenderTaskData,
20};
21
22pub const VERTEX_TEXTURE_EXTRA_ROWS: i32 = 10;
23
24pub const MAX_VERTEX_TEXTURE_WIDTH: usize = webrender_build::MAX_VERTEX_TEXTURE_WIDTH;
25
26pub mod desc {
27    use crate::device::{VertexAttribute, VertexAttributeKind, VertexDescriptor};
28
29    pub const PRIM_INSTANCES: VertexDescriptor = VertexDescriptor {
30        vertex_attributes: &[VertexAttribute {
31            name: "aPosition",
32            count: 2,
33            kind: VertexAttributeKind::U8Norm,
34        }],
35        instance_attributes: &[VertexAttribute {
36            name: "aData",
37            count: 4,
38            kind: VertexAttributeKind::I32,
39        }],
40    };
41
42    pub const BLUR: VertexDescriptor = VertexDescriptor {
43        vertex_attributes: &[VertexAttribute {
44            name: "aPosition",
45            count: 2,
46            kind: VertexAttributeKind::U8Norm,
47        }],
48        instance_attributes: &[
49            VertexAttribute {
50                name: "aBlurRenderTaskAddress",
51                count: 1,
52                kind: VertexAttributeKind::U16,
53            },
54            VertexAttribute {
55                name: "aBlurSourceTaskAddress",
56                count: 1,
57                kind: VertexAttributeKind::U16,
58            },
59            VertexAttribute {
60                name: "aBlurDirection",
61                count: 1,
62                kind: VertexAttributeKind::I32,
63            },
64        ],
65    };
66
67    pub const LINE: VertexDescriptor = VertexDescriptor {
68        vertex_attributes: &[VertexAttribute {
69            name: "aPosition",
70            count: 2,
71            kind: VertexAttributeKind::U8Norm,
72        }],
73        instance_attributes: &[
74            VertexAttribute {
75                name: "aTaskRect",
76                count: 4,
77                kind: VertexAttributeKind::F32,
78            },
79            VertexAttribute {
80                name: "aLocalSize",
81                count: 2,
82                kind: VertexAttributeKind::F32,
83            },
84            VertexAttribute {
85                name: "aWavyLineThickness",
86                count: 1,
87                kind: VertexAttributeKind::F32,
88            },
89            VertexAttribute {
90                name: "aStyle",
91                count: 1,
92                kind: VertexAttributeKind::I32,
93            },
94            VertexAttribute {
95                name: "aAxisSelect",
96                count: 1,
97                kind: VertexAttributeKind::F32,
98            },
99        ],
100    };
101
102    pub const FAST_LINEAR_GRADIENT: VertexDescriptor = VertexDescriptor {
103        vertex_attributes: &[VertexAttribute {
104            name: "aPosition",
105            count: 2,
106            kind: VertexAttributeKind::U8Norm,
107        }],
108        instance_attributes: &[
109            VertexAttribute {
110                name: "aTaskRect",
111                count: 4,
112                kind: VertexAttributeKind::F32,
113            },
114            VertexAttribute {
115                name: "aColor0",
116                count: 4,
117                kind: VertexAttributeKind::F32,
118            },
119            VertexAttribute {
120                name: "aColor1",
121                count: 4,
122                kind: VertexAttributeKind::F32,
123            },
124            VertexAttribute {
125                name: "aAxisSelect",
126                count: 1,
127                kind: VertexAttributeKind::F32,
128            },
129        ],
130    };
131
132    pub const LINEAR_GRADIENT: VertexDescriptor = VertexDescriptor {
133        vertex_attributes: &[VertexAttribute {
134            name: "aPosition",
135            count: 2,
136            kind: VertexAttributeKind::U8Norm,
137        }],
138        instance_attributes: &[
139            VertexAttribute {
140                name: "aTaskRect",
141                count: 4,
142                kind: VertexAttributeKind::F32,
143            },
144            VertexAttribute {
145                name: "aStartPoint",
146                count: 2,
147                kind: VertexAttributeKind::F32,
148            },
149            VertexAttribute {
150                name: "aEndPoint",
151                count: 2,
152                kind: VertexAttributeKind::F32,
153            },
154            VertexAttribute {
155                name: "aScale",
156                count: 2,
157                kind: VertexAttributeKind::F32,
158            },
159            VertexAttribute {
160                name: "aExtendMode",
161                count: 1,
162                kind: VertexAttributeKind::I32,
163            },
164            VertexAttribute {
165                name: "aGradientStopsAddress",
166                count: 1,
167                kind: VertexAttributeKind::I32,
168            },
169        ],
170    };
171
172    pub const RADIAL_GRADIENT: VertexDescriptor = VertexDescriptor {
173        vertex_attributes: &[VertexAttribute {
174            name: "aPosition",
175            count: 2,
176            kind: VertexAttributeKind::U8Norm,
177        }],
178        instance_attributes: &[
179            VertexAttribute {
180                name: "aTaskRect",
181                count: 4,
182                kind: VertexAttributeKind::F32,
183            },
184            VertexAttribute {
185                name: "aCenter",
186                count: 2,
187                kind: VertexAttributeKind::F32,
188            },
189            VertexAttribute {
190                name: "aScale",
191                count: 2,
192                kind: VertexAttributeKind::F32,
193            },
194            VertexAttribute {
195                name: "aStartRadius",
196                count: 1,
197                kind: VertexAttributeKind::F32,
198            },
199            VertexAttribute {
200                name: "aEndRadius",
201                count: 1,
202                kind: VertexAttributeKind::F32,
203            },
204            VertexAttribute {
205                name: "aXYRatio",
206                count: 1,
207                kind: VertexAttributeKind::F32,
208            },
209            VertexAttribute {
210                name: "aExtendMode",
211                count: 1,
212                kind: VertexAttributeKind::I32,
213            },
214            VertexAttribute {
215                name: "aGradientStopsAddress",
216                count: 1,
217                kind: VertexAttributeKind::I32,
218            },
219        ],
220    };
221
222    pub const CONIC_GRADIENT: VertexDescriptor = VertexDescriptor {
223        vertex_attributes: &[VertexAttribute {
224            name: "aPosition",
225            count: 2,
226            kind: VertexAttributeKind::U8Norm,
227        }],
228        instance_attributes: &[
229            VertexAttribute {
230                name: "aTaskRect",
231                count: 4,
232                kind: VertexAttributeKind::F32,
233            },
234            VertexAttribute {
235                name: "aCenter",
236                count: 2,
237                kind: VertexAttributeKind::F32,
238            },
239            VertexAttribute {
240                name: "aScale",
241                count: 2,
242                kind: VertexAttributeKind::F32,
243            },
244            VertexAttribute {
245                name: "aStartOffset",
246                count: 1,
247                kind: VertexAttributeKind::F32,
248            },
249            VertexAttribute {
250                name: "aEndOffset",
251                count: 1,
252                kind: VertexAttributeKind::F32,
253            },
254            VertexAttribute {
255                name: "aAngle",
256                count: 1,
257                kind: VertexAttributeKind::F32,
258            },
259            VertexAttribute {
260                name: "aExtendMode",
261                count: 1,
262                kind: VertexAttributeKind::I32,
263            },
264            VertexAttribute {
265                name: "aGradientStopsAddress",
266                count: 1,
267                kind: VertexAttributeKind::I32,
268            },
269        ],
270    };
271
272    pub const BORDER: VertexDescriptor = VertexDescriptor {
273        vertex_attributes: &[VertexAttribute {
274            name: "aPosition",
275            count: 2,
276            kind: VertexAttributeKind::U8Norm,
277        }],
278        instance_attributes: &[
279            VertexAttribute {
280                name: "aTaskOrigin",
281                count: 2,
282                kind: VertexAttributeKind::F32,
283            },
284            VertexAttribute {
285                name: "aRect",
286                count: 4,
287                kind: VertexAttributeKind::F32,
288            },
289            VertexAttribute {
290                name: "aColor0",
291                count: 4,
292                kind: VertexAttributeKind::F32,
293            },
294            VertexAttribute {
295                name: "aColor1",
296                count: 4,
297                kind: VertexAttributeKind::F32,
298            },
299            VertexAttribute {
300                name: "aFlags",
301                count: 1,
302                kind: VertexAttributeKind::I32,
303            },
304            VertexAttribute {
305                name: "aWidths",
306                count: 2,
307                kind: VertexAttributeKind::F32,
308            },
309            VertexAttribute {
310                name: "aRadii",
311                count: 2,
312                kind: VertexAttributeKind::F32,
313            },
314            VertexAttribute {
315                name: "aClipParams1",
316                count: 4,
317                kind: VertexAttributeKind::F32,
318            },
319            VertexAttribute {
320                name: "aClipParams2",
321                count: 4,
322                kind: VertexAttributeKind::F32,
323            },
324        ],
325    };
326
327    pub const SCALE: VertexDescriptor = VertexDescriptor {
328        vertex_attributes: &[VertexAttribute {
329            name: "aPosition",
330            count: 2,
331            kind: VertexAttributeKind::U8Norm,
332        }],
333        instance_attributes: &[
334            VertexAttribute {
335                name: "aScaleTargetRect",
336                count: 4,
337                kind: VertexAttributeKind::F32,
338            },
339            VertexAttribute {
340                name: "aScaleSourceRect",
341                count: 4,
342                kind: VertexAttributeKind::F32,
343            },
344        ],
345    };
346
347    pub const CLIP_RECT: VertexDescriptor = VertexDescriptor {
348        vertex_attributes: &[VertexAttribute {
349            name: "aPosition",
350            count: 2,
351            kind: VertexAttributeKind::U8Norm,
352        }],
353        instance_attributes: &[
354            // common clip attributes
355            VertexAttribute {
356                name: "aClipDeviceArea",
357                count: 4,
358                kind: VertexAttributeKind::F32,
359            },
360            VertexAttribute {
361                name: "aClipOrigins",
362                count: 4,
363                kind: VertexAttributeKind::F32,
364            },
365            VertexAttribute {
366                name: "aDevicePixelScale",
367                count: 1,
368                kind: VertexAttributeKind::F32,
369            },
370            VertexAttribute {
371                name: "aTransformIds",
372                count: 2,
373                kind: VertexAttributeKind::I32,
374            },
375            // specific clip attributes
376            VertexAttribute {
377                name: "aClipLocalPos",
378                count: 2,
379                kind: VertexAttributeKind::F32,
380            },
381            VertexAttribute {
382                name: "aClipLocalRect",
383                count: 4,
384                kind: VertexAttributeKind::F32,
385            },
386            VertexAttribute {
387                name: "aClipMode",
388                count: 1,
389                kind: VertexAttributeKind::F32,
390            },
391            VertexAttribute {
392                name: "aClipRect_TL",
393                count: 4,
394                kind: VertexAttributeKind::F32,
395            },
396            VertexAttribute {
397                name: "aClipRadii_TL",
398                count: 4,
399                kind: VertexAttributeKind::F32,
400            },
401            VertexAttribute {
402                name: "aClipRect_TR",
403                count: 4,
404                kind: VertexAttributeKind::F32,
405            },
406            VertexAttribute {
407                name: "aClipRadii_TR",
408                count: 4,
409                kind: VertexAttributeKind::F32,
410            },
411            VertexAttribute {
412                name: "aClipRect_BL",
413                count: 4,
414                kind: VertexAttributeKind::F32,
415            },
416            VertexAttribute {
417                name: "aClipRadii_BL",
418                count: 4,
419                kind: VertexAttributeKind::F32,
420            },
421            VertexAttribute {
422                name: "aClipRect_BR",
423                count: 4,
424                kind: VertexAttributeKind::F32,
425            },
426            VertexAttribute {
427                name: "aClipRadii_BR",
428                count: 4,
429                kind: VertexAttributeKind::F32,
430            },
431        ],
432    };
433
434    pub const CLIP_BOX_SHADOW: VertexDescriptor = VertexDescriptor {
435        vertex_attributes: &[VertexAttribute {
436            name: "aPosition",
437            count: 2,
438            kind: VertexAttributeKind::U8Norm,
439        }],
440        instance_attributes: &[
441            // common clip attributes
442            VertexAttribute {
443                name: "aClipDeviceArea",
444                count: 4,
445                kind: VertexAttributeKind::F32,
446            },
447            VertexAttribute {
448                name: "aClipOrigins",
449                count: 4,
450                kind: VertexAttributeKind::F32,
451            },
452            VertexAttribute {
453                name: "aDevicePixelScale",
454                count: 1,
455                kind: VertexAttributeKind::F32,
456            },
457            VertexAttribute {
458                name: "aTransformIds",
459                count: 2,
460                kind: VertexAttributeKind::I32,
461            },
462            // specific clip attributes
463            VertexAttribute {
464                name: "aClipDataResourceAddress",
465                count: 2,
466                kind: VertexAttributeKind::U16,
467            },
468            VertexAttribute {
469                name: "aClipSrcRectSize",
470                count: 2,
471                kind: VertexAttributeKind::F32,
472            },
473            VertexAttribute {
474                name: "aClipMode",
475                count: 1,
476                kind: VertexAttributeKind::I32,
477            },
478            VertexAttribute {
479                name: "aStretchMode",
480                count: 2,
481                kind: VertexAttributeKind::I32,
482            },
483            VertexAttribute {
484                name: "aClipDestRect",
485                count: 4,
486                kind: VertexAttributeKind::F32,
487            },
488        ],
489    };
490
491    pub const CLIP_IMAGE: VertexDescriptor = VertexDescriptor {
492        vertex_attributes: &[VertexAttribute {
493            name: "aPosition",
494            count: 2,
495            kind: VertexAttributeKind::U8Norm,
496        }],
497        instance_attributes: &[
498            // common clip attributes
499            VertexAttribute {
500                name: "aClipDeviceArea",
501                count: 4,
502                kind: VertexAttributeKind::F32,
503            },
504            VertexAttribute {
505                name: "aClipOrigins",
506                count: 4,
507                kind: VertexAttributeKind::F32,
508            },
509            VertexAttribute {
510                name: "aDevicePixelScale",
511                count: 1,
512                kind: VertexAttributeKind::F32,
513            },
514            VertexAttribute {
515                name: "aTransformIds",
516                count: 2,
517                kind: VertexAttributeKind::I32,
518            },
519            // specific clip attributes
520            VertexAttribute {
521                name: "aClipTileRect",
522                count: 4,
523                kind: VertexAttributeKind::F32,
524            },
525            VertexAttribute {
526                name: "aClipDataResourceAddress",
527                count: 2,
528                kind: VertexAttributeKind::U16,
529            },
530            VertexAttribute {
531                name: "aClipLocalRect",
532                count: 4,
533                kind: VertexAttributeKind::F32,
534            },
535        ],
536    };
537
538    pub const GPU_CACHE_UPDATE: VertexDescriptor = VertexDescriptor {
539        vertex_attributes: &[
540            VertexAttribute {
541                name: "aPosition",
542                count: 2,
543                kind: VertexAttributeKind::U16Norm,
544            },
545            VertexAttribute {
546                name: "aValue",
547                count: 4,
548                kind: VertexAttributeKind::F32,
549            },
550        ],
551        instance_attributes: &[],
552    };
553
554    pub const RESOLVE: VertexDescriptor = VertexDescriptor {
555        vertex_attributes: &[VertexAttribute {
556            name: "aPosition",
557            count: 2,
558            kind: VertexAttributeKind::U8Norm,
559        }],
560        instance_attributes: &[VertexAttribute {
561            name: "aRect",
562            count: 4,
563            kind: VertexAttributeKind::F32,
564        }],
565    };
566
567    pub const SVG_FILTER: VertexDescriptor = VertexDescriptor {
568        vertex_attributes: &[VertexAttribute {
569            name: "aPosition",
570            count: 2,
571            kind: VertexAttributeKind::U8Norm,
572        }],
573        instance_attributes: &[
574            VertexAttribute {
575                name: "aFilterRenderTaskAddress",
576                count: 1,
577                kind: VertexAttributeKind::U16,
578            },
579            VertexAttribute {
580                name: "aFilterInput1TaskAddress",
581                count: 1,
582                kind: VertexAttributeKind::U16,
583            },
584            VertexAttribute {
585                name: "aFilterInput2TaskAddress",
586                count: 1,
587                kind: VertexAttributeKind::U16,
588            },
589            VertexAttribute {
590                name: "aFilterKind",
591                count: 1,
592                kind: VertexAttributeKind::U16,
593            },
594            VertexAttribute {
595                name: "aFilterInputCount",
596                count: 1,
597                kind: VertexAttributeKind::U16,
598            },
599            VertexAttribute {
600                name: "aFilterGenericInt",
601                count: 1,
602                kind: VertexAttributeKind::U16,
603            },
604            VertexAttribute {
605                name: "aFilterExtraDataAddress",
606                count: 2,
607                kind: VertexAttributeKind::U16,
608            },
609        ],
610    };
611
612    pub const VECTOR_STENCIL: VertexDescriptor = VertexDescriptor {
613        vertex_attributes: &[VertexAttribute {
614            name: "aPosition",
615            count: 2,
616            kind: VertexAttributeKind::U8Norm,
617        }],
618        instance_attributes: &[
619            VertexAttribute {
620                name: "aFromPosition",
621                count: 2,
622                kind: VertexAttributeKind::F32,
623            },
624            VertexAttribute {
625                name: "aCtrlPosition",
626                count: 2,
627                kind: VertexAttributeKind::F32,
628            },
629            VertexAttribute {
630                name: "aToPosition",
631                count: 2,
632                kind: VertexAttributeKind::F32,
633            },
634            VertexAttribute {
635                name: "aFromNormal",
636                count: 2,
637                kind: VertexAttributeKind::F32,
638            },
639            VertexAttribute {
640                name: "aCtrlNormal",
641                count: 2,
642                kind: VertexAttributeKind::F32,
643            },
644            VertexAttribute {
645                name: "aToNormal",
646                count: 2,
647                kind: VertexAttributeKind::F32,
648            },
649            VertexAttribute {
650                name: "aPathID",
651                count: 1,
652                kind: VertexAttributeKind::U16,
653            },
654            VertexAttribute {
655                name: "aPad",
656                count: 1,
657                kind: VertexAttributeKind::U16,
658            },
659        ],
660    };
661
662    pub const VECTOR_COVER: VertexDescriptor = VertexDescriptor {
663        vertex_attributes: &[VertexAttribute {
664            name: "aPosition",
665            count: 2,
666            kind: VertexAttributeKind::U8Norm,
667        }],
668        instance_attributes: &[
669            VertexAttribute {
670                name: "aTargetRect",
671                count: 4,
672                kind: VertexAttributeKind::I32,
673            },
674            VertexAttribute {
675                name: "aStencilOrigin",
676                count: 2,
677                kind: VertexAttributeKind::I32,
678            },
679            VertexAttribute {
680                name: "aSubpixel",
681                count: 1,
682                kind: VertexAttributeKind::U16,
683            },
684            VertexAttribute {
685                name: "aPad",
686                count: 1,
687                kind: VertexAttributeKind::U16,
688            },
689        ],
690    };
691
692    pub const COMPOSITE: VertexDescriptor = VertexDescriptor {
693        vertex_attributes: &[VertexAttribute {
694            name: "aPosition",
695            count: 2,
696            kind: VertexAttributeKind::U8Norm,
697        }],
698        instance_attributes: &[
699            VertexAttribute {
700                name: "aLocalRect",
701                count: 4,
702                kind: VertexAttributeKind::F32,
703            },
704            VertexAttribute {
705                name: "aDeviceClipRect",
706                count: 4,
707                kind: VertexAttributeKind::F32,
708            },
709            VertexAttribute {
710                name: "aColor",
711                count: 4,
712                kind: VertexAttributeKind::F32,
713            },
714            VertexAttribute {
715                name: "aParams",
716                count: 4,
717                kind: VertexAttributeKind::F32,
718            },
719            VertexAttribute {
720                name: "aUvRect0",
721                count: 4,
722                kind: VertexAttributeKind::F32,
723            },
724            VertexAttribute {
725                name: "aUvRect1",
726                count: 4,
727                kind: VertexAttributeKind::F32,
728            },
729            VertexAttribute {
730                name: "aUvRect2",
731                count: 4,
732                kind: VertexAttributeKind::F32,
733            },
734            VertexAttribute {
735                name: "aTransform",
736                count: 4,
737                kind: VertexAttributeKind::F32,
738            },
739        ],
740    };
741
742    pub const CLEAR: VertexDescriptor = VertexDescriptor {
743        vertex_attributes: &[VertexAttribute {
744            name: "aPosition",
745            count: 2,
746            kind: VertexAttributeKind::U8Norm,
747        }],
748        instance_attributes: &[
749            VertexAttribute {
750                name: "aRect",
751                count: 4,
752                kind: VertexAttributeKind::F32,
753            },
754            VertexAttribute {
755                name: "aColor",
756                count: 4,
757                kind: VertexAttributeKind::F32,
758            },
759        ],
760    };
761}
762
763#[derive(Debug, Copy, Clone, PartialEq)]
764pub enum VertexArrayKind {
765    Primitive,
766    Blur,
767    ClipImage,
768    ClipRect,
769    ClipBoxShadow,
770    VectorStencil,
771    VectorCover,
772    Border,
773    Scale,
774    LineDecoration,
775    FastLinearGradient,
776    LinearGradient,
777    RadialGradient,
778    ConicGradient,
779    Resolve,
780    SvgFilter,
781    Composite,
782    Clear,
783}
784
785pub struct VertexDataTexture<T> {
786    texture: Option<Texture>,
787    format: api::ImageFormat,
788    _marker: PhantomData<T>,
789}
790
791impl<T> VertexDataTexture<T> {
792    pub fn new(format: api::ImageFormat) -> Self {
793        Self {
794            texture: None,
795            format,
796            _marker: PhantomData,
797        }
798    }
799
800    /// Returns a borrow of the GPU texture. Panics if it hasn't been initialized.
801    pub fn texture(&self) -> &Texture {
802        self.texture.as_ref().unwrap()
803    }
804
805    /// Returns an estimate of the GPU memory consumed by this VertexDataTexture.
806    pub fn size_in_bytes(&self) -> usize {
807        self.texture.as_ref().map_or(0, |t| t.size_in_bytes())
808    }
809
810    pub fn update<'a>(
811        &'a mut self,
812        device: &mut Device,
813        texture_uploader: &mut TextureUploader<'a>,
814        data: &mut Vec<T>,
815    ) {
816        debug_assert!(mem::size_of::<T>() % 16 == 0);
817        let texels_per_item = mem::size_of::<T>() / 16;
818        let items_per_row = MAX_VERTEX_TEXTURE_WIDTH / texels_per_item;
819        debug_assert_ne!(items_per_row, 0);
820
821        // Ensure we always end up with a texture when leaving this method.
822        let mut len = data.len();
823        if len == 0 {
824            if self.texture.is_some() {
825                return;
826            }
827            data.reserve(items_per_row);
828            len = items_per_row;
829        } else {
830            // Extend the data array to have enough capacity to upload at least
831            // a multiple of the row size.  This ensures memory safety when the
832            // array is passed to OpenGL to upload to the GPU.
833            let extra = len % items_per_row;
834            if extra != 0 {
835                let padding = items_per_row - extra;
836                data.reserve(padding);
837                len += padding;
838            }
839        }
840
841        let needed_height = (len / items_per_row) as i32;
842        let existing_height = self
843            .texture
844            .as_ref()
845            .map_or(0, |t| t.get_dimensions().height);
846
847        // Create a new texture if needed.
848        //
849        // These textures are generally very small, which is why we don't bother
850        // with incremental updates and just re-upload every frame. For most pages
851        // they're one row each, and on stress tests like css-francine they end up
852        // in the 6-14 range. So we size the texture tightly to what we need (usually
853        // 1), and shrink it if the waste would be more than `VERTEX_TEXTURE_EXTRA_ROWS`
854        // rows. This helps with memory overhead, especially because there are several
855        // instances of these textures per Renderer.
856        if needed_height > existing_height
857            || needed_height + VERTEX_TEXTURE_EXTRA_ROWS < existing_height
858        {
859            // Drop the existing texture, if any.
860            if let Some(t) = self.texture.take() {
861                device.delete_texture(t);
862            }
863
864            let texture = device.create_texture(
865                api::ImageBufferKind::Texture2D,
866                self.format,
867                MAX_VERTEX_TEXTURE_WIDTH as i32,
868                // Ensure height is at least two to work around
869                // https://bugs.chromium.org/p/angleproject/issues/detail?id=3039
870                needed_height.max(2),
871                TextureFilter::Nearest,
872                None,
873            );
874            self.texture = Some(texture);
875        }
876
877        // Note: the actual width can be larger than the logical one, with a few texels
878        // of each row unused at the tail. This is needed because there is still hardware
879        // (like Intel iGPUs) that prefers power-of-two sizes of textures ([1]).
880        //
881        // [1] https://software.intel.com/en-us/articles/opengl-performance-tips-power-of-two-textures-have-better-performance
882        let logical_width = if needed_height == 1 {
883            data.len() * texels_per_item
884        } else {
885            MAX_VERTEX_TEXTURE_WIDTH - (MAX_VERTEX_TEXTURE_WIDTH % texels_per_item)
886        };
887
888        let rect = DeviceIntRect::from_size(
889            DeviceIntSize::new(logical_width as i32, needed_height),
890        );
891
892        debug_assert!(len <= data.capacity(), "CPU copy will read out of bounds");
893        texture_uploader.upload(
894            device,
895            self.texture(),
896            rect,
897            None,
898            None,
899            data.as_ptr(),
900            len,
901        );
902    }
903
904    pub fn deinit(mut self, device: &mut Device) {
905        if let Some(t) = self.texture.take() {
906            device.delete_texture(t);
907        }
908    }
909}
910
911pub struct VertexDataTextures {
912    prim_header_f_texture: VertexDataTexture<PrimitiveHeaderF>,
913    prim_header_i_texture: VertexDataTexture<PrimitiveHeaderI>,
914    transforms_texture: VertexDataTexture<TransformData>,
915    render_task_texture: VertexDataTexture<RenderTaskData>,
916}
917
918impl VertexDataTextures {
919    pub fn new() -> Self {
920        VertexDataTextures {
921            prim_header_f_texture: VertexDataTexture::new(api::ImageFormat::RGBAF32),
922            prim_header_i_texture: VertexDataTexture::new(api::ImageFormat::RGBAI32),
923            transforms_texture: VertexDataTexture::new(api::ImageFormat::RGBAF32),
924            render_task_texture: VertexDataTexture::new(api::ImageFormat::RGBAF32),
925        }
926    }
927
928    pub fn update(&mut self, device: &mut Device, pbo_pool: &mut UploadPBOPool, frame: &mut Frame) {
929        let mut texture_uploader = device.upload_texture(pbo_pool);
930        self.prim_header_f_texture.update(
931            device,
932            &mut texture_uploader,
933            &mut frame.prim_headers.headers_float,
934        );
935        self.prim_header_i_texture.update(
936            device,
937            &mut texture_uploader,
938            &mut frame.prim_headers.headers_int,
939        );
940        self.transforms_texture
941            .update(device, &mut texture_uploader, &mut frame.transform_palette);
942        self.render_task_texture.update(
943            device,
944            &mut texture_uploader,
945            &mut frame.render_tasks.task_data,
946        );
947
948        // Flush and drop the texture uploader now, so that
949        // we can borrow the textures to bind them.
950        texture_uploader.flush(device);
951
952        device.bind_texture(
953            super::TextureSampler::PrimitiveHeadersF,
954            &self.prim_header_f_texture.texture(),
955            Swizzle::default(),
956        );
957        device.bind_texture(
958            super::TextureSampler::PrimitiveHeadersI,
959            &self.prim_header_i_texture.texture(),
960            Swizzle::default(),
961        );
962        device.bind_texture(
963            super::TextureSampler::TransformPalette,
964            &self.transforms_texture.texture(),
965            Swizzle::default(),
966        );
967        device.bind_texture(
968            super::TextureSampler::RenderTasks,
969            &self.render_task_texture.texture(),
970            Swizzle::default(),
971        );
972    }
973
974    pub fn size_in_bytes(&self) -> usize {
975        self.prim_header_f_texture.size_in_bytes()
976            + self.prim_header_i_texture.size_in_bytes()
977            + self.transforms_texture.size_in_bytes()
978            + self.render_task_texture.size_in_bytes()
979    }
980
981    pub fn deinit(self, device: &mut Device) {
982        self.transforms_texture.deinit(device);
983        self.prim_header_f_texture.deinit(device);
984        self.prim_header_i_texture.deinit(device);
985        self.render_task_texture.deinit(device);
986    }
987}
988
989pub struct RendererVAOs {
990    prim_vao: VAO,
991    blur_vao: VAO,
992    clip_rect_vao: VAO,
993    clip_box_shadow_vao: VAO,
994    clip_image_vao: VAO,
995    border_vao: VAO,
996    line_vao: VAO,
997    scale_vao: VAO,
998    fast_linear_gradient_vao: VAO,
999    linear_gradient_vao: VAO,
1000    radial_gradient_vao: VAO,
1001    conic_gradient_vao: VAO,
1002    resolve_vao: VAO,
1003    svg_filter_vao: VAO,
1004    composite_vao: VAO,
1005    clear_vao: VAO,
1006}
1007
1008impl RendererVAOs {
1009    pub fn new(device: &mut Device, indexed_quads: Option<NonZeroUsize>) -> Self {
1010        const QUAD_INDICES: [u16; 6] = [0, 1, 2, 2, 1, 3];
1011        const QUAD_VERTICES: [[u8; 2]; 4] = [[0, 0], [0xFF, 0], [0, 0xFF], [0xFF, 0xFF]];
1012
1013        let instance_divisor = if indexed_quads.is_some() { 0 } else { 1 };
1014        let prim_vao = device.create_vao(&desc::PRIM_INSTANCES, instance_divisor);
1015
1016        device.bind_vao(&prim_vao);
1017        match indexed_quads {
1018            Some(count) => {
1019                assert!(count.get() < u16::MAX as usize);
1020                let quad_indices = (0 .. count.get() as u16)
1021                    .flat_map(|instance| QUAD_INDICES.iter().map(move |&index| instance * 4 + index))
1022                    .collect::<Vec<_>>();
1023                device.update_vao_indices(&prim_vao, &quad_indices, VertexUsageHint::Static);
1024                let quad_vertices = (0 .. count.get() as u16)
1025                    .flat_map(|_| QUAD_VERTICES.iter().cloned())
1026                    .collect::<Vec<_>>();
1027                device.update_vao_main_vertices(&prim_vao, &quad_vertices, VertexUsageHint::Static);
1028            }
1029            None => {
1030                device.update_vao_indices(&prim_vao, &QUAD_INDICES, VertexUsageHint::Static);
1031                device.update_vao_main_vertices(&prim_vao, &QUAD_VERTICES, VertexUsageHint::Static);
1032            }
1033        }
1034
1035        RendererVAOs {
1036            blur_vao: device.create_vao_with_new_instances(&desc::BLUR, &prim_vao),
1037            clip_rect_vao: device.create_vao_with_new_instances(&desc::CLIP_RECT, &prim_vao),
1038            clip_box_shadow_vao: device
1039                .create_vao_with_new_instances(&desc::CLIP_BOX_SHADOW, &prim_vao),
1040            clip_image_vao: device.create_vao_with_new_instances(&desc::CLIP_IMAGE, &prim_vao),
1041            border_vao: device.create_vao_with_new_instances(&desc::BORDER, &prim_vao),
1042            scale_vao: device.create_vao_with_new_instances(&desc::SCALE, &prim_vao),
1043            line_vao: device.create_vao_with_new_instances(&desc::LINE, &prim_vao),
1044            fast_linear_gradient_vao: device.create_vao_with_new_instances(&desc::FAST_LINEAR_GRADIENT, &prim_vao),
1045            linear_gradient_vao: device.create_vao_with_new_instances(&desc::LINEAR_GRADIENT, &prim_vao),
1046            radial_gradient_vao: device.create_vao_with_new_instances(&desc::RADIAL_GRADIENT, &prim_vao),
1047            conic_gradient_vao: device.create_vao_with_new_instances(&desc::CONIC_GRADIENT, &prim_vao),
1048            resolve_vao: device.create_vao_with_new_instances(&desc::RESOLVE, &prim_vao),
1049            svg_filter_vao: device.create_vao_with_new_instances(&desc::SVG_FILTER, &prim_vao),
1050            composite_vao: device.create_vao_with_new_instances(&desc::COMPOSITE, &prim_vao),
1051            clear_vao: device.create_vao_with_new_instances(&desc::CLEAR, &prim_vao),
1052            prim_vao,
1053        }
1054    }
1055
1056    pub fn deinit(self, device: &mut Device) {
1057        device.delete_vao(self.prim_vao);
1058        device.delete_vao(self.resolve_vao);
1059        device.delete_vao(self.clip_rect_vao);
1060        device.delete_vao(self.clip_box_shadow_vao);
1061        device.delete_vao(self.clip_image_vao);
1062        device.delete_vao(self.fast_linear_gradient_vao);
1063        device.delete_vao(self.linear_gradient_vao);
1064        device.delete_vao(self.radial_gradient_vao);
1065        device.delete_vao(self.conic_gradient_vao);
1066        device.delete_vao(self.blur_vao);
1067        device.delete_vao(self.line_vao);
1068        device.delete_vao(self.border_vao);
1069        device.delete_vao(self.scale_vao);
1070        device.delete_vao(self.svg_filter_vao);
1071        device.delete_vao(self.composite_vao);
1072        device.delete_vao(self.clear_vao);
1073    }
1074}
1075
1076impl ops::Index<VertexArrayKind> for RendererVAOs {
1077    type Output = VAO;
1078    fn index(&self, kind: VertexArrayKind) -> &VAO {
1079        match kind {
1080            VertexArrayKind::Primitive => &self.prim_vao,
1081            VertexArrayKind::ClipImage => &self.clip_image_vao,
1082            VertexArrayKind::ClipRect => &self.clip_rect_vao,
1083            VertexArrayKind::ClipBoxShadow => &self.clip_box_shadow_vao,
1084            VertexArrayKind::Blur => &self.blur_vao,
1085            VertexArrayKind::VectorStencil | VertexArrayKind::VectorCover => unreachable!(),
1086            VertexArrayKind::Border => &self.border_vao,
1087            VertexArrayKind::Scale => &self.scale_vao,
1088            VertexArrayKind::LineDecoration => &self.line_vao,
1089            VertexArrayKind::FastLinearGradient => &self.fast_linear_gradient_vao,
1090            VertexArrayKind::LinearGradient => &self.linear_gradient_vao,
1091            VertexArrayKind::RadialGradient => &self.radial_gradient_vao,
1092            VertexArrayKind::ConicGradient => &self.conic_gradient_vao,
1093            VertexArrayKind::Resolve => &self.resolve_vao,
1094            VertexArrayKind::SvgFilter => &self.svg_filter_vao,
1095            VertexArrayKind::Composite => &self.composite_vao,
1096            VertexArrayKind::Clear => &self.clear_vao,
1097        }
1098    }
1099}