Flutter Engine
The Flutter Engine
Public Member Functions | Protected Member Functions | List of all members
ClipTileRenderer Class Referenceabstract
Inheritance diagram for ClipTileRenderer:
SkRefCntBase DebugTileRenderer SolidColorRenderer TextureSetRenderer YUVTextureSetRenderer

Public Member Functions

virtual int drawTile (SkCanvas *canvas, const SkRect &rect, const SkPoint clip[4], const bool edgeAA[4], int tileID, int quadID)=0
 
virtual void drawBanner (SkCanvas *canvas)=0
 
virtual int drawTiles (SkCanvas *canvas)
 
- Public Member Functions inherited from SkRefCntBase
 SkRefCntBase ()
 
virtual ~SkRefCntBase ()
 
bool unique () const
 
void ref () const
 
void unref () const
 

Protected Member Functions

SkCanvas::QuadAAFlags maskToFlags (const bool edgeAA[4]) const
 
int clipTile (SkCanvas *canvas, int tileID, const SkRect &baseRect, const SkPoint quad[4], const bool edgeAA[4], const SkPoint lines[], int lineCount, int *quadCount)
 

Detailed Description

Definition at line 205 of file compositor_quads.cpp.

Member Function Documentation

◆ clipTile()

int ClipTileRenderer::clipTile ( SkCanvas canvas,
int  tileID,
const SkRect baseRect,
const SkPoint  quad[4],
const bool  edgeAA[4],
const SkPoint  lines[],
int  lineCount,
int quadCount 
)
inlineprotected

Definition at line 265 of file compositor_quads.cpp.

266 {
267 if (lineCount == 0) {
268 // No lines, so end recursion by drawing the tile. If the tile was never split then
269 // 'quad' remains null so that drawTile() can differentiate how it should draw.
270 int draws = this->drawTile(canvas, baseRect, quad, edgeAA, tileID, *quadCount);
271 *quadCount = *quadCount + 1;
272 return draws;
273 }
274
275 static constexpr int kTL = 0; // Top-left point index in points array
276 static constexpr int kTR = 1; // Top-right point index in points array
277 static constexpr int kBR = 2; // Bottom-right point index in points array
278 static constexpr int kBL = 3; // Bottom-left point index in points array
279 static constexpr int kS0 = 4; // First split point index in points array
280 static constexpr int kS1 = 5; // Second split point index in points array
281
282 SkPoint points[6];
283 if (quad) {
284 // Copy the original 4 points into set of points to consider
285 for (int i = 0; i < 4; ++i) {
286 points[i] = quad[i];
287 }
288 } else {
289 // Haven't been split yet, so fill in based on the rect
290 baseRect.toQuad(points);
291 }
292
293 // Consider the first line against the 4 quad edges in tile, which should have 0,1, or 2
294 // intersection points since the tile is convex.
295 int splitIndices[2]; // Edge that was intersected
296 int intersectionCount = 0;
297 for (int i = 0; i < 4; ++i) {
299 if (intersect_line_segments(points[i], points[i == 3 ? 0 : i + 1],
300 lines[0], lines[1], &intersect)) {
301 // If the intersected point is the same as the last found intersection, the line
302 // runs through a vertex, so don't double count it
303 bool duplicate = false;
304 for (int j = 0; j < intersectionCount; ++j) {
305 if (SkScalarNearlyZero((intersect - points[kS0 + j]).length())) {
306 duplicate = true;
307 break;
308 }
309 }
310 if (!duplicate) {
311 points[kS0 + intersectionCount] = intersect;
312 splitIndices[intersectionCount] = i;
313 intersectionCount++;
314 }
315 }
316 }
317
318 if (intersectionCount < 2) {
319 // Either the first line never intersected the quad (count == 0), or it intersected at a
320 // single vertex without going through quad area (count == 1), so check next line
321 return this->clipTile(
322 canvas, tileID, baseRect, quad, edgeAA, lines + 2, lineCount - 1, quadCount);
323 }
324
325 SkASSERT(intersectionCount == 2);
326 // Split the tile points into 2+ sub quads and recurse to the next lines, which may or may
327 // not further split the tile. Since the configurations are relatively simple, the possible
328 // splits are hardcoded below; subtile quad orderings are such that the sub tiles remain in
329 // clockwise order and match expected edges for QuadAAFlags. subtile indices refer to the
330 // 6-element 'points' array.
332 int s2 = -1; // Index of an original vertex chosen for a artificial split
333 if (splitIndices[1] - splitIndices[0] == 2) {
334 // Opposite edges, so the split trivially forms 2 sub quads
335 if (splitIndices[0] == 0) {
336 subtiles.push_back({{kTL, kS0, kS1, kBL}});
337 subtiles.push_back({{kS0, kTR, kBR, kS1}});
338 } else {
339 subtiles.push_back({{kTL, kTR, kS0, kS1}});
340 subtiles.push_back({{kS1, kS0, kBR, kBL}});
341 }
342 } else {
343 // Adjacent edges, which makes for a more complicated split, since it forms a degenerate
344 // quad (triangle) and a pentagon that must be artificially split. The pentagon is split
345 // using one of the original vertices (remembered in 's2'), which adds an additional
346 // degenerate quad, but ensures there are no T-junctions.
347 switch(splitIndices[0]) {
348 case 0:
349 // Could be connected to edge 1 or edge 3
350 if (splitIndices[1] == 1) {
351 s2 = kBL;
352 subtiles.push_back({{kS0, kTR, kS1, kS0}}); // degenerate
353 subtiles.push_back({{kTL, kS0, edgeAA[0] ? kS0 : kBL, kBL}}); // degenerate
354 subtiles.push_back({{kS0, kS1, kBR, kBL}});
355 } else {
356 SkASSERT(splitIndices[1] == 3);
357 s2 = kBR;
358 subtiles.push_back({{kTL, kS0, kS1, kS1}}); // degenerate
359 subtiles.push_back({{kS1, edgeAA[3] ? kS1 : kBR, kBR, kBL}}); // degenerate
360 subtiles.push_back({{kS0, kTR, kBR, kS1}});
361 }
362 break;
363 case 1:
364 // Edge 0 handled above, should only be connected to edge 2
365 SkASSERT(splitIndices[1] == 2);
366 s2 = kTL;
367 subtiles.push_back({{kS0, kS0, kBR, kS1}}); // degenerate
368 subtiles.push_back({{kTL, kTR, kS0, edgeAA[1] ? kS0 : kTL}}); // degenerate
369 subtiles.push_back({{kTL, kS0, kS1, kBL}});
370 break;
371 case 2:
372 // Edge 1 handled above, should only be connected to edge 3
373 SkASSERT(splitIndices[1] == 3);
374 s2 = kTR;
375 subtiles.push_back({{kS1, kS0, kS0, kBL}}); // degenerate
376 subtiles.push_back({{edgeAA[2] ? kS0 : kTR, kTR, kBR, kS0}}); // degenerate
377 subtiles.push_back({{kTL, kTR, kS0, kS1}});
378 break;
379 case 3:
380 // Fall through, an adjacent edge split that hits edge 3 should have first found
381 // been found with edge 0 or edge 2 for the other end
382 default:
383 SkASSERT(false);
384 return 0;
385 }
386 }
387
388 SkPoint sub[4];
389 bool subAA[4];
390 int draws = 0;
391 for (int i = 0; i < subtiles.size(); ++i) {
392 // Fill in the quad points and update edge AA rules for new interior edges
393 for (int j = 0; j < 4; ++j) {
394 int p = subtiles[i][j];
395 sub[j] = points[p];
396
397 int np = j == 3 ? subtiles[i][0] : subtiles[i][j + 1];
398 // The "new" edges are the edges that connect between the two split points or
399 // between a split point and the chosen s2 point. Otherwise the edge remains aligned
400 // with the original shape, so should preserve the AA setting.
401 if ((p >= kS0 && (np == s2 || np >= kS0)) ||
402 ((np >= kS0) && (p == s2 || p >= kS0))) {
403 // New edge
404 subAA[j] = false;
405 } else {
406 // The subtiles indices were arranged so that their edge ordering was still top,
407 // right, bottom, left so 'j' can be used to access edgeAA
408 subAA[j] = edgeAA[j];
409 }
410 }
411
412 // Split the sub quad with the next line
413 draws += this->clipTile(canvas, tileID, baseRect, sub, subAA, lines + 2, lineCount - 1,
414 quadCount);
415 }
416 return draws;
417 }
static bool intersect(const SkPoint &p0, const SkPoint &n0, const SkPoint &p1, const SkPoint &n1, SkScalar *t)
static const uint16_t kTL
static const uint16_t kBL
static const uint16_t kBR
static const uint16_t kTR
static const int points[]
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
virtual int drawTile(SkCanvas *canvas, const SkRect &rect, const SkPoint clip[4], const bool edgeAA[4], int tileID, int quadID)=0
int clipTile(SkCanvas *canvas, int tileID, const SkRect &baseRect, const SkPoint quad[4], const bool edgeAA[4], const SkPoint lines[], int lineCount, int *quadCount)
int size() const
Definition: SkTArray.h:421
static bool intersect_line_segments(const SkPoint &p0, const SkPoint &p1, const SkPoint &l0, const SkPoint &l1, SkPoint *intersect)
size_t length
void toQuad(SkPoint quad[4]) const
Definition: SkRect.cpp:50

◆ drawBanner()

virtual void ClipTileRenderer::drawBanner ( SkCanvas canvas)
pure virtual

◆ drawTile()

virtual int ClipTileRenderer::drawTile ( SkCanvas canvas,
const SkRect rect,
const SkPoint  clip[4],
const bool  edgeAA[4],
int  tileID,
int  quadID 
)
pure virtual

◆ drawTiles()

virtual int ClipTileRenderer::drawTiles ( SkCanvas canvas)
inlinevirtual

Reimplemented in TextureSetRenderer, and YUVTextureSetRenderer.

Definition at line 220 of file compositor_quads.cpp.

220 {
221 // All three lines in a list
222 SkPoint lines[6];
226
227 bool edgeAA[4];
228 int tileID = 0;
229 int drawCount = 0;
230 for (int i = 0; i < kRowCount; ++i) {
231 for (int j = 0; j < kColCount; ++j) {
232 // The unclipped tile geometry
235 // Base edge AA flags if there are no clips; clipped lines will only turn off edges
236 edgeAA[0] = i == 0; // Top
237 edgeAA[1] = j == kColCount - 1; // Right
238 edgeAA[2] = i == kRowCount - 1; // Bottom
239 edgeAA[3] = j == 0; // Left
240
241 // Now clip against the 3 lines formed by kClipPx and split into general purpose
242 // quads as needed.
243 int quadCount = 0;
244 drawCount += this->clipTile(canvas, tileID, tile, nullptr, edgeAA, lines, 3,
245 &quadCount);
246 tileID++;
247 }
248 }
249
250 return drawCount;
251 }
static void clipping_line_segment(const SkPoint &p0, const SkPoint &p1, SkPoint line[2])
static constexpr SkPoint kClipP2
static constexpr SkScalar kTileHeight
static constexpr SkScalar kTileWidth
static constexpr int kRowCount
static constexpr SkPoint kClipP3
static constexpr int kColCount
static constexpr SkPoint kClipP1
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659

◆ maskToFlags()

SkCanvas::QuadAAFlags ClipTileRenderer::maskToFlags ( const bool  edgeAA[4]) const
inlineprotected

Definition at line 254 of file compositor_quads.cpp.

254 {
255 unsigned flags = (edgeAA[0] * SkCanvas::kTop_QuadAAFlag) |
256 (edgeAA[1] * SkCanvas::kRight_QuadAAFlag) |
257 (edgeAA[2] * SkCanvas::kBottom_QuadAAFlag) |
258 (edgeAA[3] * SkCanvas::kLeft_QuadAAFlag);
259 return static_cast<SkCanvas::QuadAAFlags>(flags);
260 }
@ kTop_QuadAAFlag
Definition: SkCanvas.h:1660
@ kRight_QuadAAFlag
Definition: SkCanvas.h:1661
@ kLeft_QuadAAFlag
Definition: SkCanvas.h:1659
@ kBottom_QuadAAFlag
Definition: SkCanvas.h:1662
FlutterSemanticsFlag flags

The documentation for this class was generated from the following file: