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