Các cấu trúc dữ liệu chính trong RenderingNG

Chris Harrelson
Chris Harrelson
Daniel Cheng
Daniel Cheng
Philip Rogers
Philip Rogers
Koji Ishi
Koji Ishi
Ian Kilpatrick
Ian Kilpatrick
Kyle Charbonneau
Kyle Charbonneau

Hãy xem các cấu trúc dữ liệu chính, đó là dữ liệu đầu vào và đầu ra cho quy trình hiển thị.

Các cấu trúc dữ liệu này bao gồm:

  • Cây khung bao gồm các nút cục bộ và nút từ xa đại diện cho tài liệu nằm trong quá trình kết xuất và trình kết xuất Blink.
  • Cây mảnh không thể thay đổi thể hiện đầu ra của (và đầu vào) thuật toán ràng buộc bố cục.
  • Cây thuộc tính thể hiện hệ phân cấp biến đổi, cắt đoạn, hiệu ứng và cuộn của một tài liệu web. Các thông báo này được sử dụng trong toàn bộ quy trình.
  • Danh sách hiển thị và phân đoạn tô màu là dữ liệu đầu vào cho thuật toán đường quét và thuật toán phân lớp.
  • Khung hình tổng hợp bao bọc các bề mặt, bề mặt kết xuất và hoạ tiết GPU ô dùng để vẽ bằng GPU.

Trước khi tìm hiểu các cấu trúc dữ liệu này, ví dụ sau đây dựa trên thứ nhất là đánh giá cấu trúc. Chiến dịch này ví dụ được sử dụng xuyên suốt tài liệu này kèm theo minh hoạ về cách dữ liệu có áp dụng cấu trúc nào.

<!-- Example code -->
<html>
  <div style="overflow: hidden; width: 100px; height: 100px;">
    <iframe style="filter: blur(3px);
      transform: rotateZ(1deg);
      width: 100px; height: 300px"
      id="one" src="foo.com/etc"></iframe>
  </div>
  <iframe style="top:200px;
    transform: scale(1.1) translateX(200px)"
    id="two" src="bar.com"></iframe>
</html>

Cây khung

Đôi khi, Chrome có thể chọn hiển thị một khung trên nhiều nguồn gốc trong quá trình kết xuất khác với khung hình mẹ.

Trong mã ví dụ, có tổng cộng 3 khung hình:

Khung chính foo.com, chứa hai iframe.

Với tính năng tách biệt trang web, Chromium sử dụng hai quy trình kết xuất để kết xuất trang web này. Mỗi quá trình kết xuất có đại diện riêng cho cây khung cho trang web đó:

Hai cây khung đại diện cho hai quá trình kết xuất.

Khung hình kết xuất trong một quy trình khác được biểu thị dưới dạng khung từ xa. Khung hình từ xa chứa thông tin tối thiểu cần thiết để hoạt động như một phần giữ chỗ trong quá trình kết xuất, chẳng hạn như tham số. Nếu không, khung từ xa không chứa bất kỳ thông tin nào cần thiết để kết xuất nội dung thực tế.

Ngược lại, một khung cục bộ biểu thị một khung đi qua tiêu chuẩn quy trình kết xuất hình ảnh. Khung cục bộ chứa tất cả thông tin cần thiết để bật dữ liệu cho khung đó (như cây DOM và dữ liệu kiểu) thành một thứ gì đó có thể hiển thị và hiển thị.

Quy trình kết xuất hoạt động ở mức độ chi tiết của mảnh cây khung cục bộ. Hãy xem xét một ví dụ phức tạp hơn với foo.com là khung chính:

<iframe src="bar.com"></iframe>

bar.com khung phụ sau:

<iframe src="foo.com/etc"></iframe>

Mặc dù vẫn chỉ có 2 trình kết xuất đồ hoạ nhưng hiện có 3 khung hình cục bộ các mảnh cây, với hai mảnh trong quá trình kết xuất cho foo.com và một trong quá trình kết xuất cho bar.com:

Hình minh hoạ 2 kết xuất và 3 mảnh cây khung.

Để tạo một khung trình tổng hợp cho trang web, Viz yêu cầu đồng thời một khung trình tổng hợp từ khung gốc của mỗi 3 cây khung cục bộ, sau đó tổng hợp chúng. Hãy tham khảo thêm phần khung trình tổng hợp.

Khung chính foo.com và khung phụ foo.com/other-page đều là một phần của cùng một cây khung và được kết xuất trong cùng một quy trình. Tuy nhiên, hai khung này vẫn có vòng đời tài liệu vì chúng là một phần của nhiều mảnh cây khung cục bộ. Do đó, bạn không thể tạo một khung trình tổng hợp cho cả hai trong một lần cập nhật. Quá trình kết xuất không có đủ thông tin để kết hợp khung trình tổng hợp được tạo cho foo.com/other-page trực tiếp vào khung trình kết hợp cho khung chính foo.com. Ví dụ: khung mẹ bar.com ngoài quy trình có thể ảnh hưởng đến việc hiển thị iframe foo.com/other-url, bằng cách chuyển đổi iframe bằng CSS hoặc che khuất các phần của iframe với các phần tử khác trong DOM.

Thác nước cập nhật thuộc tính hình ảnh

Các thuộc tính trực quan (như hệ số tỷ lệ của thiết bị và kích thước khung nhìn) ảnh hưởng đến kết quả hiển thị và phải được đồng bộ hoá giữa các mảnh cây khung cục bộ. Gốc của mỗi mảnh cây khung cục bộ có một đối tượng tiện ích được liên kết với nó. Nội dung cập nhật thuộc tính hình ảnh sẽ được đưa vào tiện ích của khung chính trước khi phổ biến vào các tiện ích còn lại từ trên xuống dưới.

Ví dụ: khi kích thước khung nhìn thay đổi:

Sơ đồ về quy trình được giải thích trong văn bản trước.

Quá trình này không diễn ra ngay lập tức, vì vậy, các thuộc tính hình ảnh được sao chép cũng bao gồm mã thông báo đồng bộ hoá. Trình tổng hợp Viz sử dụng mã thông báo đồng bộ hoá này để chờ tất cả các mảnh cây khung cục bộ để gửi khung trình tổng hợp có mã thông báo đồng bộ hoá hiện tại. Quá trình này tránh kết hợp các khung trình tổng hợp có các thuộc tính hình ảnh khác nhau.

Cây mảnh bất biến

Cây mảnh bất biến là kết quả của giai đoạn bố cục trong quá trình kết xuất quy trình. Thứ nguyên này thể hiện vị trí và kích thước của tất cả thành phần trên trang (không áp dụng phép biến đổi).

Giá trị đại diện của các mảnh trong mỗi cây, với một mảnh được đánh dấu là cần bố cục.

Mỗi mảnh đại diện cho một phần của phần tử DOM. Thông thường, chỉ có một mảnh trong mỗi phần tử, nhưng có thể có nhiều hơn nếu được chia nhỏ trên các trang khác nhau khi in, hoặc cột khi ở trong ngữ cảnh nhiều cột.

Sau bố cục, mỗi mảnh trở thành không thể thay đổi và không bao giờ thay đổi lại. Một điều quan trọng là chúng tôi cũng đặt ra thêm một số quy định hạn chế. Chúng tôi không:

  • Cho phép mọi thao tác "lên" tham chiếu trong cây. (Phần tử con không thể có con trỏ trỏ đến phần tử mẹ.)
  • "bong bóng" dữ liệu dưới dạng cây (phần tử con chỉ đọc thông tin của phần tử con chứ không đọc thông tin của phần tử mẹ).

Những hạn chế này cho phép chúng ta sử dụng lại một mảnh cho bố cục tiếp theo. Nếu không có những hạn chế này, chúng tôi thường phải tái tạo toàn bộ cây, việc này rất tốn kém.

Hầu hết bố cục thường là cập nhật gia tăng, ví dụ: một ứng dụng web cập nhật một phần nhỏ trên giao diện người dùng để phản hồi khi người dùng nhấp vào một phần tử. Tốt nhất là bố cục chỉ nên hoạt động tương xứng với những gì thực sự thay đổi trên màn hình. Chúng ta có thể làm việc này bằng cách sử dụng lại nhiều phần của cây trước đó nhất có thể. Điều này có nghĩa là (thường) chúng ta chỉ cần xây dựng lại gáy của cây.

Trong tương lai, thiết kế bất biến này có thể cho phép chúng tôi làm những điều thú vị chẳng hạn như truyền cây mảnh không thể thay đổi qua ranh giới luồng nếu cần (để thực hiện các giai đoạn tiếp theo trên một luồng khác), tạo nhiều cây để ảnh động bố cục mượt mà, hoặc thực hiện các bố cục suy đoán song song. Điều này cũng cho chúng ta biết tiềm năng của chính bố cục đa luồng.

Mục trong mảnh cùng dòng

Nội dung cùng dòng (chủ yếu theo kiểu) sử dụng cách trình bày hơi khác. Thay vì một cấu trúc cây với các hộp và con trỏ, chúng tôi sẽ trình bày nội dung cùng dòng trong một danh sách phẳng biểu thị cây. Lợi ích chính là việc biểu diễn danh sách phẳng cho nội tuyến nhanh chóng, hữu ích cho việc kiểm tra hoặc truy vấn cấu trúc dữ liệu cùng dòng, và hiệu quả về bộ nhớ. Điều này cực kỳ quan trọng đối với hiệu suất kết xuất web, vì việc hiển thị văn bản là rất phức tạp, và có thể dễ dàng trở thành phần chậm nhất của quy trình trừ phi được tối ưu hoá cao.

Danh sách phẳng được tạo cho mỗi ngữ cảnh định dạng cùng dòng theo thứ tự tìm kiếm theo chiều sâu của cây con bố cục cùng dòng. Mỗi mục trong danh sách là một bộ dữ liệu (đối tượng, số lượng thành phần con). Ví dụ: hãy xem xét DOM này:

<div style="width: 0;">
  <span style="color: blue; position: relative;">Hi</span> <b>there</b>.
</div>

Thuộc tính width được đặt thành 0 để dòng ngắt giữa "Xin chào" và "ở đó".

Khi ngữ cảnh định dạng cùng dòng cho trường hợp này được thể hiện dưới dạng cây, kết quả sẽ như sau:

{
  "Line box": {
    "Box <span>": {
      "Text": "Hi"
    }
  },
  "Line box": {
    "Box <b>": {
      "Text": "There"
    }
  },
  {
    "Text": "."
  }
}

Danh sách phẳng có dạng như sau:

  • (Hộp dòng, 2)
  • (Hộp <span>, 1)
  • (Văn bản "Xin chào", 0)
  • (Hộp dòng, 3)
  • (Hộp <b>, 1)
  • (Văn bản "ở đó", 0)
  • (Văn bản ".", 0)

Có rất nhiều đối tượng sử dụng cấu trúc dữ liệu này: API hỗ trợ tiếp cận, và hình học, chẳng hạn như getClientRects! và contenteditable. Mỗi loại sẽ có những yêu cầu khác nhau. Các thành phần này truy cập vào cấu trúc dữ liệu phẳng thông qua một con trỏ tiện lợi.

Con trỏ có các API, chẳng hạn như MoveToNext, MoveToNextLine, CursorForChildren. Biểu diễn con trỏ này rất hiệu quả đối với nội dung văn bản vì nhiều lý do:

  • Việc lặp lại theo thứ tự tìm kiếm theo chiều sâu rất nhanh. Phương pháp này được sử dụng rất thường xuyên vì tương tự như cử động con nháy. Vì đây là danh sách phẳng nên phương thức tìm kiếm theo chiều sâu chỉ làm tăng độ lệch mảng, cung cấp vòng lặp nhanh và vị trí bộ nhớ.
  • Tính năng này cung cấp tìm kiếm theo chiều rộng, cần thiết khi, ví dụ: tô lên nền của dòng kẻ và ô cùng dòng.
  • Biết được số lượng con cháu giúp việc di chuyển sang phần tử con tiếp theo nhanh chóng hơn (chỉ tăng độ lệch mảng theo số đó).

Cây tài sản

DOM là một cây các phần tử (cùng với các nút văn bản) và CSS có thể áp dụng nhiều kiểu vào phần tử.

Điều này xuất hiện theo 4 cách:

  • Bố cục: đầu vào cho thuật toán ràng buộc bố cục.
  • Sơn: cách tô và tạo điểm ảnh cho phần tử (nhưng không phải các thành phần con cháu của nó).
  • Hình ảnh: hiệu ứng đường quét/vẽ được áp dụng cho cây con DOM, chẳng hạn như biến đổi, bộ lọc và đoạn video.
  • Cuộn: góc căn chỉnh theo trục và tròn cắt và cuộn của cây con chứa trong đó.

Cây thuộc tính là các cấu trúc dữ liệu giải thích cách các hiệu ứng hình ảnh và cuộn áp dụng cho các phần tử DOM. Các hệ thống này đưa ra phương tiện để trả lời các câu hỏi như: ở đâu, so với màn hình, là một phần tử DOM nhất định, dựa trên kích thước bố cục và vị trí? Và: nên sử dụng trình tự hoạt động GPU nào để áp dụng hiệu ứng hình ảnh và cuộn?

Hiệu ứng hình ảnh và hiệu ứng cuộn trên web rất phức tạp nếu xét đến tận cùng là vô cùng hiệu quả. Vì vậy, điều quan trọng nhất mà cây thuộc tính làm được là chuyển đổi sự phức tạp thành một cấu trúc dữ liệu duy nhất thể hiện chính xác cấu trúc và ý nghĩa của chúng, đồng thời loại bỏ phần còn lại của sự phức tạp của DOM và CSS. Điều này cho phép chúng tôi triển khai các thuật toán để tổng hợp và cuộn một cách tự tin hơn nhiều. Cụ thể:

  • Hình học có thể dễ xảy ra lỗi và các phép tính khác có thể được tập trung vào cùng một nơi.
  • Tính phức tạp của việc xây dựng và cập nhật cây tài sản tách riêng thành một giai đoạn quy trình kết xuất hình ảnh.
  • Việc gửi cây thuộc tính xung quanh các luồng và quy trình khác nhau dễ dàng và nhanh chóng hơn nhiều so với trạng thái DOM đầy đủ, nhờ đó, bạn có thể sử dụng chúng cho nhiều trường hợp sử dụng.
  • Càng có nhiều trường hợp sử dụng, chúng ta càng giành được nhiều thành công hơn từ việc lưu vào bộ nhớ đệm hình học được xây dựng trên cùng, vì chúng có thể sử dụng lại bộ nhớ đệm.

Quá trình kết xuấtNG sử dụng cây thuộc tính cho nhiều mục đích, chẳng hạn như:

  • Tách hoạt động tổng hợp khỏi sự kiện vẽ và hoạt động kết hợp khỏi luồng chính.
  • Xác định chiến lược kết hợp / rút tối ưu.
  • Đang đo IntersectionObserver hình học.
  • Tránh sử dụng cho các thành phần ngoài màn hình và ô hoạ tiết GPU.
  • Làm mất hiệu lực sơn và đường quét một cách hiệu quả và chính xác.
  • Đang đo thay đổi bố cụcnội dung lớn nhất hiển thị trong Chỉ số quan trọng chính của trang web.

Mỗi tài liệu web có 4 cây thuộc tính riêng biệt: biến đổi, cắt đoạn, hiệu ứng và cuộn.(*) Cây biến đổi thể hiện các biến đổi và cuộn CSS. (Một biến đổi cuộn được biểu thị dưới dạng ma trận biến đổi 2D.) Cây đoạn video đại diện cho clip bổ sung. Cây hiệu ứng thể hiện tất cả các hiệu ứng hình ảnh khác: độ mờ, bộ lọc, mặt nạ, chế độ phối màu và các loại clip khác như clip-path. Cây cuộn biểu thị thông tin về thao tác cuộn, chẳng hạn như cách cuộn tạo chuỗi với nhau; cần thực hiện thao tác cuộn trên luồng trình tổng hợp. Mỗi nút trong cây thuộc tính đại diện cho một hiệu ứng cuộn hoặc hiệu ứng hình ảnh do một phần tử DOM áp dụng. Nếu để tình huống đó có nhiều hiệu ứng, có thể có nhiều nút cây thuộc tính trong mỗi cây cho cùng một phần tử.

Cấu trúc liên kết của mỗi cây giống như một bản trình bày DOM thưa thớt. Ví dụ: nếu có ba phần tử DOM có các đoạn video tràn, thì sẽ có 3 nút cây clip, và cấu trúc của cây đoạn video sẽ tuân theo mối quan hệ khối chứa giữa các đoạn mã bị tràn. Ngoài ra còn có các mối liên kết giữa các cây. Các đường liên kết này chỉ ra hệ phân cấp DOM tương đối, và thứ tự ứng dụng của các nút. Ví dụ: nếu một phép biến đổi trên một phần tử DOM nằm dưới một phần tử DOM khác có bộ lọc, thì tất nhiên biến đổi sẽ được áp dụng trước bộ lọc.

Mỗi phần tử DOM có một trạng thái cây thuộc tính, là một 4 bộ dữ liệu (biến đổi, cắt đoạn, hiệu ứng, cuộn) cho biết clip đối tượng cấp trên gần nhất, biến đổi và các nút cây hiệu ứng tác động lên phần tử đó. Cách này rất thuận tiện, vì với thông tin này, chúng ta sẽ biết chính xác danh sách các đoạn video, biến đổi và hiệu ứng áp dụng cho phần tử đó, và thứ tự sắp xếp. Thông tin này cho chúng tôi biết vị trí của khung hiển thị trên màn hình và cách vẽ.

Ví dụ:

(nguồn)

<html>
  <div style="overflow: scroll; width: 100px; height: 100px;">
    <iframe style="filter: blur(3px);
      transform: rotateZ(1deg);
      width: 100px; height: 300px"
  id="one" srcdoc="iframe one"></iframe>
  </div>
  <iframe style="top:200px;
      transform: scale(1.1) translateX(200px)" id=two
      srcdoc="iframe two"></iframe>
</html>

Đối với ví dụ trước (có đôi chút khác biệt so với ví dụ ở phần giới thiệu), sau đây là các thành phần chính của cây tài sản được tạo:

Ví dụ về các phần tử trong cây tài sản.

Hiển thị danh sách và vẽ các phần

Một mục hiển thị chứa các lệnh vẽ cấp thấp (xem tại đây) có thể tạo điểm ảnh bằng Skia. Các mục trên màn hình thường đơn giản, chỉ cần một vài lệnh vẽ, chẳng hạn như vẽ đường viền hoặc nền. Bước đi trên cây sơn sẽ lặp lại cây bố cục và các mảnh liên quan theo thứ tự vẽ CSS để tạo danh sách mặt hàng trưng bày.

Ví dụ:

Một hộp màu xanh dương có dòng chữ &quot;Hello world&quot; (&quot;Xin chào thế giới&quot;) bên trong một hình chữ nhật màu xanh lục.

<div id="green" style="background:green; width:80px;">
    Hello world
</div>
<div id="blue" style="width:100px;
  height:100px; background:blue;
  position:absolute;
  top:0; left:0; z-index:-1;">
</div>

HTML và CSS này sẽ tạo danh sách hiển thị sau đây, trong đó mỗi ô là một mục hiển thị:

Nền chế độ xem #blue (âm thanh trong nền) #green (âm thanh trong nền) #green văn bản cùng dòng
drawRect có kích thước 800x600 và có màu trắng. drawRect có kích thước 100x100 ở vị trí 0.0 và có màu xanh dương. drawRect có kích thước 80x18 ở vị trí 8.8 và có màu xanh lục. drawTextBlob ở vị trí 8,8 và dòng chữ "Hello world".

Danh sách mặt hàng hiển thị được sắp xếp từ sau ra trước. Trong ví dụ trên, div màu xanh lục nằm trước div màu xanh dương theo thứ tự DOM, nhưng thứ tự hiển thị CSS yêu cầu phải vẽ div z-index âm màu xanh dương trước (bước 3) div màu xanh lục (bước 4.1). Các mục hiển thị gần như tương ứng với các bước không thể phân chia trong quy cách đơn đặt hàng sơn CSS. Một phần tử DOM duy nhất có thể khiến nhiều mặt hàng hiển thị, chẳng hạn như cách #green có một mục hiển thị ở chế độ nền và một mục hiển thị khác cho văn bản cùng dòng. Mức độ chi tiết này rất quan trọng để thể hiện đầy đủ mức độ phức tạp của thông số kỹ thuật của đơn đặt hàng sơn CSS, chẳng hạn như xen kẽ do lề âm tạo ra:

Một hình chữ nhật màu xanh lục có hộp màu xám phủ một phần và dòng chữ &quot;Hello world&quot;.

<div id="green" style="background:green; width:80px;">
    Hello world
</div>
<div id="gray" style="width:35px; height:20px;
  background:gray;margin-top:-10px;"></div>

Thao tác này sẽ tạo ra danh sách hiển thị sau đây, trong đó mỗi ô là một mục hiển thị:

Nền chế độ xem #green (âm thanh trong nền) #gray (âm thanh trong nền) #green văn bản cùng dòng
drawRect có kích thước 800x600 và có màu trắng. drawRect có kích thước 80x18 ở vị trí 8.8 và có màu xanh lục. drawRect có kích thước 35x20 ở vị trí 8,16 và màu xám. drawTextBlob ở vị trí 8,8 và dòng chữ "Hello world".

Danh sách mặt hàng hiển thị được lưu trữ và sử dụng lại trong các lần cập nhật sau này. Nếu một đối tượng bố cục không thay đổi trong quá trình đi bộ trên cây sơn, các mục hiển thị được sao chép từ danh sách trước. Việc tối ưu hoá bổ sung dựa trên một thuộc tính của quy cách đơn đặt hàng hiển thị CSS: các bối cảnh xếp chồng vẽ một cách tỉ mỉ. Nếu không có đối tượng bố cục nào thay đổi trong ngữ cảnh xếp chồng, bước đi trên cây sơn bỏ qua ngữ cảnh xếp chồng và sao chép toàn bộ chuỗi các mặt hàng hiển thị từ danh sách trước.

Trạng thái cây tài sản hiện tại được duy trì trong quá trình đi bộ để tạo cây sơn và danh sách mặt hàng hiển thị được nhóm thành "các khúc" của các mục hiển thị có cùng trạng thái cây thuộc tính. Điều này được minh hoạ trong ví dụ sau:

Một chiếc hộp màu hồng với một hộp màu cam nghiêng.

<div id="scroll" style="background:pink; width:100px;
   height:100px; overflow:scroll;
   position:absolute; top:0; left:0;">
    Hello world
    <div id="orange" style="width:75px; height:200px;
      background:orange; transform:rotateZ(25deg);">
        I'm falling
    </div>
</div>

Thao tác này sẽ tạo ra danh sách hiển thị sau đây, trong đó mỗi ô là một mục hiển thị:

Nền chế độ xem #scroll (âm thanh trong nền) #scroll văn bản cùng dòng #orange (âm thanh trong nền) #orange văn bản cùng dòng
drawRect có kích thước 800x600 và có màu trắng. drawRect có kích thước 100x100 ở vị trí 0.0 và có màu hồng. drawTextBlob với vị trí 0.0 và dòng chữ "Hello world". drawRect có kích thước 75x200 tại vị trí 0.0 và có màu cam. drawTextBlob với vị trí 0.0 và dòng chữ "Tôi đang ngã".

Sau đó, cây thuộc tính biến đổi và các đoạn sơn sẽ được (được đơn giản hoá cho ngắn gọn):

Hình ảnh của bảng trước, hai ô đầu tiên trong phân đoạn 1, ô thứ ba trong phân đoạn 2, hai ô cuối cùng trong phân đoạn 3.

Danh sách các khối sơn theo thứ tự, đó là các nhóm các mục hiển thị và trạng thái cây thuộc tính, là đầu vào cho bước phân lớp của quy trình kết xuất. Toàn bộ danh sách các phần sơn có thể được hợp nhất thành một lớp tổng hợp và tạo điểm ảnh lại với nhau, nhưng điều này sẽ yêu cầu tạo điểm ảnh tốn kém mỗi khi người dùng cuộn. Có thể tạo một lớp tổng hợp cho mỗi đoạn sơn và tạo điểm ảnh riêng lẻ để tránh tất cả quá trình tái tạo điểm ảnh, nhưng điều đó sẽ nhanh chóng làm cạn kiệt bộ nhớ GPU. Bước phân lớp phải đưa ra sự đánh đổi giữa bộ nhớ GPU và giảm chi phí khi mọi thứ thay đổi. Một cách tiếp cận chung hay là hợp nhất các phần theo mặc định, và không hợp nhất các phần sơn có trạng thái cây thuộc tính dự kiến sẽ thay đổi trên luồng của trình tổng hợp, chẳng hạn như với hoạt ảnh cuộn luồng trình tổng hợp hoặc ảnh động biến đổi luồng trình tổng hợp.

Ví dụ trước tốt nhất nên tạo ra 2 lớp tổng hợp:

  • Một lớp tổng hợp có kích thước 800x600 chứa các lệnh vẽ:
    1. drawRect có kích thước 800x600 và màu trắng
    2. drawRect có kích thước 100x100 ở vị trí 0.0 và màu hồng
  • Một lớp tổng hợp 144x224 chứa các lệnh vẽ:
    1. drawTextBlob với vị trí là 0,0 và dòng chữ "Hello world" ("Xin chào thế giới")
    2. dịch 0,18
    3. rotateZ(25deg)
    4. drawRect có kích thước 75x200 tại vị trí 0.0 và có màu cam
    5. drawTextBlob với vị trí 0.0 và dòng chữ "Tôi sắp giảm"

Nếu người dùng cuộn #scroll, lớp tổng hợp thứ hai được di chuyển, nhưng không cần tạo điểm ảnh.

Ví dụ: từ phần trước về cây thuộc tính, có 6 mảng sơn. Cùng với các trạng thái cây thuộc tính (biến đổi, cắt, hiệu ứng, cuộn) của chúng, chúng là:

  • Nền tài liệu: cuộn tài liệu, đoạn trích tài liệu, gốc, cuộn tài liệu.
  • Góc ngang, dọc và cuộn cho div (ba phần sơn riêng biệt): cuộn tài liệu, đoạn trích tài liệu, làm mờ #one, cuộn tài liệu.
  • Khung nội tuyến #one: #one xoay, đoạn video cuộn tràn, làm mờ #one, cuộn div.
  • Iframe #two: Tỷ lệ #two, đoạn trích tài liệu, thư mục gốc, cuộn tài liệu.

Khung tổng hợp: bề mặt, bề mặt kết xuất và ô hoạ tiết GPU

Trình duyệt và quá trình kết xuất quản lý việc tạo điểm ảnh của nội dung, sau đó gửi các khung hình tổng hợp đến quy trình Viz để hiển thị lên màn hình. Khung bộ tổng hợp trình bày cách ghép nội dung đã tạo điểm ảnh lại với nhau và vẽ nó hiệu quả bằng cách sử dụng GPU.

Thẻ thông tin

Trên lý thuyết, quá trình hiển thị hoặc trình tổng hợp quy trình của trình duyệt có thể tạo điểm ảnh cho pixel thành một kết cấu duy nhất kích thước đầy đủ của khung nhìn trình kết xuất và gửi kết cấu đó đến Viz. Để hiển thị màn hình, trình tổng hợp hiển thị chỉ cần sao chép pixel từ hoạ tiết đó vào vị trí thích hợp trong vùng đệm khung (ví dụ: màn hình). Tuy nhiên, nếu trình tổng hợp đó muốn cập nhật một pixel cần thiết để tạo lại đường quét toàn bộ khung nhìn và gửi hoạ tiết mới cho Viz.

Thay vào đó, khung nhìn được chia thành các ô. Một ô hoạ tiết GPU riêng biệt phía sau mỗi ô có các pixel đã tạo điểm ảnh cho một phần của khung nhìn. Sau đó, trình kết xuất có thể cập nhật từng thẻ thông tin hoặc thậm chí chỉ cần thay đổi vị trí trên màn hình cho các ô hiện có. Ví dụ: khi cuộn một trang web, vị trí của các ô hiện có sẽ dịch chuyển lên trên và chỉ thỉnh thoảng một thẻ thông tin mới sẽ cần được tạo điểm ảnh cho nội dung ở phía dưới trang.

4 ô.
Hình ảnh này mô tả một ngày nắng, với 4 ô. Khi một lượt cuộn diễn ra, ô thứ năm sẽ bắt đầu xuất hiện. Một trong số các thẻ thông tin chỉ có một màu (xanh da trời), có một video và iframe ở trên cùng.

Bốn phần và nền tảng

Ô hoạ tiết GPU là một loại quad đặc biệt, đây chỉ là tên gọi tạm thời của một loại hoạ tiết hoặc loại khác. Một góc quad xác định hoạ tiết đầu vào, đồng thời cho biết cách chuyển đổi và áp dụng hiệu ứng hình ảnh cho hoạ tiết đó. Ví dụ: ô nội dung thông thường có phép biến đổi cho biết vị trí x, y của chúng trong lưới ô.

Ô kết cấu GPU.

Những thẻ thông tin đã tạo điểm ảnh này được gói trong một lượt kết xuất, là một danh sách các quads. Thẻ kết xuất không chứa bất kỳ thông tin pixel nào; thay vào đó, nó có hướng dẫn về vị trí và cách vẽ từng bốn hình để tạo đầu ra pixel mong muốn. Có một 4 hình vẽ cho mỗi ô kết cấu GPU. Trình tổng hợp hiển thị chỉ phải lặp lại danh sách các quads, vẽ từng đối tượng bằng các hiệu ứng hình ảnh cụ thể, để tạo đầu ra pixel mong muốn cho lượt kết xuất. Việc tổng hợp các góc vẽ cho một lượt kết xuất có thể được thực hiện hiệu quả trên GPU, vì hiệu ứng hình ảnh được cho phép được chọn kỹ lưỡng là những hiệu ứng ánh xạ trực tiếp đến các tính năng GPU.

Ngoài các ô được tạo điểm ảnh, còn có các loại ô vẽ khác. Ví dụ: có các tứ giác vẽ màu đồng nhất không hề được hoạ tiết hỗ trợ, hoặc tứ giác vẽ hoạ tiết cho các hoạ tiết không xếp kề như video hoặc canvas.

Khung của trình tổng hợp cũng có thể nhúng một khung của trình tổng hợp khác. Ví dụ: trình tổng hợp trình duyệt tạo ra một khung trình tổng hợp có giao diện người dùng trình duyệt, và một hình chữ nhật trống nơi nội dung trình tổng hợp kết xuất sẽ được nhúng. Một ví dụ khác là iframe được tách biệt trang web. Việc nhúng này được thực hiện thông qua các nền tảng.

Khi trình tổng hợp gửi một khung trình tổng hợp, khung đó kèm theo một giá trị nhận dạng, có tên là Surface ID, cho phép các khung tổng hợp khác nhúng nó theo tham chiếu. Viz lưu trữ khung trình tổng hợp mới nhất được gửi kèm theo mã nền tảng cụ thể. Sau đó, một khung trình tổng hợp khác có thể tham chiếu đến khung đó sau thông qua khung vẽ bề mặt, và vì thế Viz biết cần vẽ gì. (Lưu ý rằng các góc vẽ bề mặt chỉ chứa mã nhận dạng bề mặt chứ không chứa hoạ tiết.)

Lượt kết xuất trung gian

Một số hiệu ứng hình ảnh, chẳng hạn như nhiều bộ lọc hoặc chế độ kết hợp nâng cao, yêu cầu vẽ 2 hoặc nhiều tứ giác trên hoạ tiết trung gian. Sau đó, hoạ tiết trung gian được vẽ vào vùng đệm đích trên GPU (hoặc có thể là một hoạ tiết trung gian khác), áp dụng đồng thời hiệu ứng hình ảnh. Để cho phép điều này, khung trình tổng hợp thực sự chứa danh sách các lượt kết xuất. Luôn phải có một lượt kết xuất gốc, được vẽ cuối cùng và có đích đến tương ứng với vùng đệm khung, và có thể vẫn còn nhiều điều khác nữa.

Việc có thể có nhiều lượt kết xuất hình ảnh giải thích tên "kết xuất kết xuất". Mỗi lượt truyền phải được thực thi tuần tự trên GPU, trong nhiều "lượt truyền", trong khi một lượt truyền có thể được hoàn thành trong một phép tính GPU song song ở quy mô lớn.

Tổng hợp

Nhiều khung trình tổng hợp được gửi đến Viz, và chúng cần được vẽ cùng nhau lên màn hình. Điều này được thực hiện bằng giai đoạn tổng hợp, trong đó chuyển đổi chúng thành một khung tổng hợp. Tổng hợp thay thế các góc vẽ bề mặt bằng các khung trình tổng hợp mà chúng chỉ định. Đây cũng là cơ hội để tối ưu hoá các hoạ tiết hoặc nội dung trung gian không cần thiết nằm ngoài màn hình. Ví dụ: trong nhiều trường hợp, khung trình tổng hợp cho một iframe riêng biệt của trang web không cần có hoạ tiết trung gian, và có thể được vẽ trực tiếp vào vùng đệm khung thông qua các góc vẽ thích hợp. Giai đoạn tổng hợp sẽ chỉ ra những cách tối ưu hoá đó và áp dụng chúng dựa trên kiến thức toàn cầu mà các trình tổng hợp hiển thị riêng lẻ không thể tiếp cận.

Ví dụ:

Dưới đây là các khung trình tổng hợp đại diện cho ví dụ từ đầu bài đăng này.

  • Nền tảng foo.com/index.html: id=0
    • Kết xuất truyền 0: vẽ thành đầu ra.
      • Kết xuất đường quét quad vẽ: vẽ với hiệu ứng làm mờ 3px và cắt vào đường truyền kết xuất 0.
        • Hiển thị lượt 1:
          • Vẽ các phần tư cho nội dung ô của iframe #one, với vị trí x và y cho mỗi iframe.
      • Bề mặt vẽ quad: với mã nhận dạng 2, được vẽ theo tỷ lệ và chuyển đổi phép biến đổi.
  • Nền tảng giao diện người dùng của trình duyệt: ID=1
    • Kết xuất truyền 0: vẽ thành đầu ra.
      • Vẽ bốn góc cho giao diện người dùng của trình duyệt (cũng xếp kề)
  • Nền tảng bar.com/index.html: ID=2
    • Kết xuất truyền 0: vẽ thành đầu ra.
      • Vẽ các phần tư cho nội dung của iframe #two, với vị trí x và y cho mỗi iframe.

Ảnh minh hoạ của Una Kravets.