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