Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp

Issue 7590009: Merge 92255 - Source/WebCore: [Chromium] Use edge-distance method for layer anti-aliasing. (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/835/
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 } 77 }
78 78
79 void LayerTilerChromium::setTileSize(const IntSize& size) 79 void LayerTilerChromium::setTileSize(const IntSize& size)
80 { 80 {
81 if (m_tileSize == size) 81 if (m_tileSize == size)
82 return; 82 return;
83 83
84 reset(); 84 reset();
85 85
86 m_tileSize = size; 86 m_tileSize = size;
87 m_tilingData.setMaxTextureSize(max(size.width(), size.height()));
87 } 88 }
88 89
89 LayerTexture* LayerTilerChromium::getSingleTexture() 90 LayerTexture* LayerTilerChromium::getSingleTexture()
90 { 91 {
91 if (m_tilingData.numTiles() != 1) 92 if (m_tilingData.numTiles() != 1)
92 return 0; 93 return 0;
93 94
94 Tile* tile = tileAt(0, 0); 95 Tile* tile = tileAt(0, 0);
95 return tile ? tile->texture() : 0; 96 return tile ? tile->texture() : 0;
96 } 97 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 IntRect LayerTilerChromium::tileContentRect(const Tile* tile) const 183 IntRect LayerTilerChromium::tileContentRect(const Tile* tile) const
183 { 184 {
184 IntRect contentRect = tileLayerRect(tile); 185 IntRect contentRect = tileLayerRect(tile);
185 contentRect.move(m_layerPosition.x(), m_layerPosition.y()); 186 contentRect.move(m_layerPosition.x(), m_layerPosition.y());
186 return contentRect; 187 return contentRect;
187 } 188 }
188 189
189 IntRect LayerTilerChromium::tileLayerRect(const Tile* tile) const 190 IntRect LayerTilerChromium::tileLayerRect(const Tile* tile) const
190 { 191 {
191 const int index = m_tilingData.tileIndex(tile->i(), tile->j()); 192 const int index = m_tilingData.tileIndex(tile->i(), tile->j());
192 return m_tilingData.tileBoundsWithBorder(index); 193 IntRect layerRect = m_tilingData.tileBoundsWithBorder(index);
193 } 194 layerRect.setSize(m_tileSize);
194 195 return layerRect;
195 IntRect LayerTilerChromium::tileTexRect(const Tile* tile) const
196 {
197 const int index = m_tilingData.tileIndex(tile->i(), tile->j());
198 return m_tilingData.tileBoundsWithOuterBorder(index);
199 } 196 }
200 197
201 void LayerTilerChromium::invalidateRect(const IntRect& contentRect) 198 void LayerTilerChromium::invalidateRect(const IntRect& contentRect)
202 { 199 {
203 if (contentRect.isEmpty() || m_skipsDraw) 200 if (contentRect.isEmpty() || m_skipsDraw)
204 return; 201 return;
205 202
206 IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY());
207 const IntRect oldLayerRect = IntRect(IntPoint(), oldLayerSize);
208
209 growLayerToContain(contentRect); 203 growLayerToContain(contentRect);
210 204
211 // Dirty rects are always in layer space, as the layer could be repositioned 205 // Dirty rects are always in layer space, as the layer could be repositioned
212 // after invalidation. 206 // after invalidation.
213 const IntRect layerRect = contentRectToLayerRect(contentRect); 207 const IntRect layerRect = contentRectToLayerRect(contentRect);
214 208
215 int left, top, right, bottom; 209 int left, top, right, bottom;
216 contentRectToTileIndices(contentRect, left, top, right, bottom); 210 contentRectToTileIndices(contentRect, left, top, right, bottom);
217 for (int j = top; j <= bottom; ++j) { 211 for (int j = top; j <= bottom; ++j) {
218 for (int i = left; i <= right; ++i) { 212 for (int i = left; i <= right; ++i) {
219 Tile* tile = tileAt(i, j); 213 Tile* tile = tileAt(i, j);
220 if (!tile) 214 if (!tile)
221 continue; 215 continue;
222 IntRect bound = tileLayerRect(tile); 216 IntRect bound = tileLayerRect(tile);
223 bound.intersect(layerRect); 217 bound.intersect(layerRect);
224 tile->m_dirtyLayerRect.unite(bound); 218 tile->m_dirtyLayerRect.unite(bound);
225
226 // Invalidate old layer area to clear any contents left from
227 // previous layer size.
228 IntRect oldBound = tileLayerRect(tile);
229 oldBound.intersect(oldLayerRect);
230 tile->m_dirtyLayerRect.unite(oldBound);
231 } 219 }
232 } 220 }
233 } 221 }
234 222
235 void LayerTilerChromium::invalidateEntireLayer() 223 void LayerTilerChromium::invalidateEntireLayer()
236 { 224 {
237 for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter ) { 225 for (TileMap::iterator iter = m_tiles.begin(); iter != m_tiles.end(); ++iter ) {
238 ASSERT(iter->second->refCount() == 1); 226 ASSERT(iter->second->refCount() == 1);
239 m_unusedTiles.append(iter->second.release()); 227 m_unusedTiles.append(iter->second.release());
240 } 228 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 growLayerToContain(contentRect); 265 growLayerToContain(contentRect);
278 266
279 if (!numTiles()) { 267 if (!numTiles()) {
280 m_updateRect = IntRect(); 268 m_updateRect = IntRect();
281 return; 269 return;
282 } 270 }
283 271
284 // Create tiles as needed, expanding a dirty rect to contain all 272 // Create tiles as needed, expanding a dirty rect to contain all
285 // the dirty regions currently being drawn. 273 // the dirty regions currently being drawn.
286 IntRect dirtyLayerRect; 274 IntRect dirtyLayerRect;
287 IntSize tileSize;
288 int left, top, right, bottom; 275 int left, top, right, bottom;
289 contentRectToTileIndices(contentRect, left, top, right, bottom); 276 contentRectToTileIndices(contentRect, left, top, right, bottom);
290 for (int j = top; j <= bottom; ++j) { 277 for (int j = top; j <= bottom; ++j) {
291 for (int i = left; i <= right; ++i) { 278 for (int i = left; i <= right; ++i) {
292 Tile* tile = tileAt(i, j); 279 Tile* tile = tileAt(i, j);
293 if (!tile) 280 if (!tile)
294 tile = createTile(i, j); 281 tile = createTile(i, j);
295 282
296 IntSize texSize = tileTexRect(tile).size(); 283 if (!tile->texture()->isValid(m_tileSize, m_textureFormat))
297 if (!tile->texture()->isValid(texSize, m_textureFormat))
298 tile->m_dirtyLayerRect = tileLayerRect(tile); 284 tile->m_dirtyLayerRect = tileLayerRect(tile);
299 285
300 if (!tile->texture()->reserve(texSize, m_textureFormat)) { 286 if (!tile->texture()->reserve(m_tileSize, m_textureFormat)) {
301 m_skipsDraw = true; 287 m_skipsDraw = true;
302 reset(); 288 reset();
303 return; 289 return;
304 } 290 }
305 291
306 dirtyLayerRect.unite(tile->m_dirtyLayerRect); 292 dirtyLayerRect.unite(tile->m_dirtyLayerRect);
307
308 tileSize = tileSize.expandedTo(texSize);
309 } 293 }
310 } 294 }
311 295
312 // Due to borders, when the paint rect is extended to tile boundaries, it 296 // Due to borders, when the paint rect is extended to tile boundaries, it
313 // may end up overlapping more tiles than the original content rect. Record 297 // may end up overlapping more tiles than the original content rect. Record
314 // that original rect so we don't upload more tiles than necessary. 298 // that original rect so we don't upload more tiles than necessary.
315 m_updateRect = contentRect; 299 m_updateRect = contentRect;
316 300
317 m_paintRect = layerRectToContentRect(dirtyLayerRect); 301 m_paintRect = layerRectToContentRect(dirtyLayerRect);
318 if (dirtyLayerRect.isEmpty()) 302 if (dirtyLayerRect.isEmpty())
319 return; 303 return;
320 304
321 textureUpdater->prepareToUpdate(m_paintRect, tileSize, m_tilingData.borderTe xels()); 305 textureUpdater->prepareToUpdate(m_paintRect, m_tileSize, m_tilingData.border Texels());
322 } 306 }
323 307
324 void LayerTilerChromium::updateRect(LayerTextureUpdater* textureUpdater) 308 void LayerTilerChromium::updateRect(LayerTextureUpdater* textureUpdater)
325 { 309 {
326 // Painting could cause compositing to get turned off, which may cause the t iler to become invalidated mid-update. 310 // Painting could cause compositing to get turned off, which may cause the t iler to become invalidated mid-update.
327 if (!m_tilingData.totalSizeX() || !m_tilingData.totalSizeY() || m_updateRect .isEmpty() || !numTiles() || m_skipsDraw) 311 if (!m_tilingData.totalSizeX() || !m_tilingData.totalSizeY() || m_updateRect .isEmpty() || !numTiles() || m_skipsDraw)
328 return; 312 return;
329 313
330 GraphicsContext3D* context = layerRendererContext(); 314 GraphicsContext3D* context = layerRendererContext();
331 m_textureOrientation = textureUpdater->orientation(); 315 m_textureOrientation = textureUpdater->orientation();
332 m_sampledTexelFormat = textureUpdater->sampledTexelFormat(m_textureFormat); 316 m_sampledTexelFormat = textureUpdater->sampledTexelFormat(m_textureFormat);
333 317
334 int left, top, right, bottom; 318 int left, top, right, bottom;
335 contentRectToTileIndices(m_updateRect, left, top, right, bottom); 319 contentRectToTileIndices(m_updateRect, left, top, right, bottom);
336 for (int j = top; j <= bottom; ++j) { 320 for (int j = top; j <= bottom; ++j) {
337 for (int i = left; i <= right; ++i) { 321 for (int i = left; i <= right; ++i) {
338 Tile* tile = tileAt(i, j); 322 Tile* tile = tileAt(i, j);
339 if (!tile) 323 if (!tile)
340 tile = createTile(i, j); 324 tile = createTile(i, j);
341 else if (!tile->dirty()) 325 else if (!tile->dirty())
342 continue; 326 continue;
343 327
344 // Calculate page-space rectangle to copy from. 328 // Calculate page-space rectangle to copy from.
345 IntRect sourceRect = tileContentRect(tile); 329 IntRect sourceRect = tileContentRect(tile);
346 IntRect texRect = tileTexRect(tile); 330 const IntPoint anchor = sourceRect.location();
347 const IntPoint anchor = texRect.location();
348 sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect)) ; 331 sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect)) ;
349 // Paint rect not guaranteed to line up on tile boundaries, so 332 // Paint rect not guaranteed to line up on tile boundaries, so
350 // make sure that sourceRect doesn't extend outside of it. 333 // make sure that sourceRect doesn't extend outside of it.
351 sourceRect.intersect(m_paintRect); 334 sourceRect.intersect(m_paintRect);
352 if (sourceRect.isEmpty()) 335 if (sourceRect.isEmpty())
353 continue; 336 continue;
354 337
355 ASSERT(tile->texture()->isReserved()); 338 ASSERT(tile->texture()->isReserved());
356 339
357 // Calculate tile-space rectangle to upload into. 340 // Calculate tile-space rectangle to upload into.
(...skipping 29 matching lines...) Expand all
387 void LayerTilerChromium::setLayerPosition(const IntPoint& layerPosition) 370 void LayerTilerChromium::setLayerPosition(const IntPoint& layerPosition)
388 { 371 {
389 m_layerPosition = layerPosition; 372 m_layerPosition = layerPosition;
390 } 373 }
391 374
392 void LayerTilerChromium::draw(const IntRect& contentRect, const TransformationMa trix& globalTransform, float opacity) 375 void LayerTilerChromium::draw(const IntRect& contentRect, const TransformationMa trix& globalTransform, float opacity)
393 { 376 {
394 if (m_skipsDraw || !m_tiles.size() || contentRect.isEmpty()) 377 if (m_skipsDraw || !m_tiles.size() || contentRect.isEmpty())
395 return; 378 return;
396 379
380 // Use anti-aliasing programs when border texels are preset and transform
381 // is not an integer translation.
382 bool useAA = (m_tilingData.borderTexels() && !globalTransform.isIntegerTrans lation());
383
397 switch (m_sampledTexelFormat) { 384 switch (m_sampledTexelFormat) {
398 case LayerTextureUpdater::SampledTexelFormatRGBA: 385 case LayerTextureUpdater::SampledTexelFormatRGBA:
399 drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerP rogram()); 386 if (useAA)
387 drawTiles(contentRect, globalTransform, opacity, layerRenderer()->ti lerProgramAA(), layerRenderer()->tilerProgramAA()->fragmentShader().fragmentTexT ransformLocation(), layerRenderer()->tilerProgramAA()->fragmentShader().edgeLoca tion());
388 else
389 drawTiles(contentRect, globalTransform, opacity, layerRenderer()->ti lerProgram(), -1, -1);
400 break; 390 break;
401 case LayerTextureUpdater::SampledTexelFormatBGRA: 391 case LayerTextureUpdater::SampledTexelFormatBGRA:
402 drawTiles(contentRect, globalTransform, opacity, layerRenderer()->tilerP rogramSwizzle()); 392 if (useAA)
393 drawTiles(contentRect, globalTransform, opacity, layerRenderer()->ti lerProgramSwizzleAA(), layerRenderer()->tilerProgramSwizzleAA()->fragmentShader( ).fragmentTexTransformLocation(), layerRenderer()->tilerProgramSwizzleAA()->frag mentShader().edgeLocation());
394 else
395 drawTiles(contentRect, globalTransform, opacity, layerRenderer()->ti lerProgramSwizzle(), -1, -1);
403 break; 396 break;
404 default: 397 default:
405 ASSERT_NOT_REACHED(); 398 ASSERT_NOT_REACHED();
406 } 399 }
407 } 400 }
408 401
409 void LayerTilerChromium::growLayerToContain(const IntRect& contentRect) 402 void LayerTilerChromium::growLayerToContain(const IntRect& contentRect)
410 { 403 {
411 // Grow the tile array to contain this content rect. 404 // Grow the tile array to contain this content rect.
412 IntRect layerRect = contentRectToLayerRect(contentRect); 405 IntRect layerRect = contentRectToLayerRect(contentRect);
413 IntSize rectSize = IntSize(layerRect.maxX(), layerRect.maxY()); 406 IntSize rectSize = IntSize(layerRect.maxX(), layerRect.maxY());
414 IntSize texSize = m_tileSize;
415 407
416 // Use rect with border texels as max texture size when tile size
417 // has not been specified.
418 if (texSize.isEmpty()) {
419 texSize = rectSize;
420 if (m_tilingData.borderTexels())
421 texSize.expand(2, 2);
422 }
423
424 m_tilingData.setMaxTextureSize(max(texSize.width(), texSize.height()));
425 IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY()); 408 IntSize oldLayerSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY());
426 IntSize newSize = rectSize.expandedTo(oldLayerSize); 409 IntSize newSize = rectSize.expandedTo(oldLayerSize);
427 m_tilingData.setTotalSize(newSize.width(), newSize.height()); 410 m_tilingData.setTotalSize(newSize.width(), newSize.height());
428 } 411 }
429 412
430 static bool isCCW(const FloatQuad& quad) 413 static bool isCCW(const FloatQuad& quad)
431 { 414 {
432 FloatPoint v1 = FloatPoint(quad.p2().x() - quad.p1().x(), 415 FloatPoint v1 = FloatPoint(quad.p2().x() - quad.p1().x(),
433 quad.p2().y() - quad.p1().y()); 416 quad.p2().y() - quad.p1().y());
434 FloatPoint v2 = FloatPoint(quad.p3().x() - quad.p2().x(), 417 FloatPoint v2 = FloatPoint(quad.p3().x() - quad.p2().x(),
(...skipping 15 matching lines...) Expand all
450 } 433 }
451 434
452 static FloatPoint intersect(const Edge& a, const Edge& b) 435 static FloatPoint intersect(const Edge& a, const Edge& b)
453 { 436 {
454 return FloatPoint( 437 return FloatPoint(
455 (a.y() * b.z() - b.y() * a.z()) / (a.x() * b.y() - b.x() * a.y()), 438 (a.y() * b.z() - b.y() * a.z()) / (a.x() * b.y() - b.x() * a.y()),
456 (a.x() * b.z() - b.x() * a.z()) / (b.x() * a.y() - a.x() * b.y())); 439 (a.x() * b.z() - b.x() * a.z()) / (b.x() * a.y() - a.x() * b.y()));
457 } 440 }
458 441
459 template <class T> 442 template <class T>
460 void LayerTilerChromium::drawTiles(const IntRect& contentRect, const Transformat ionMatrix& globalTransform, float opacity, const T* program) 443 void LayerTilerChromium::drawTiles(const IntRect& contentRect, const Transformat ionMatrix& globalTransform, float opacity, const T* program, int fragmentTexTran sformLocation, int edgeLocation)
461 { 444 {
462 GraphicsContext3D* context = layerRendererContext(); 445 TransformationMatrix matrix(layerRenderer()->windowMatrix() * layerRenderer( )->projectionMatrix() * globalTransform);
463 GLC(context, context->useProgram(program->program()));
464 GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
465 GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
466
467 TransformationMatrix matrix(globalTransform);
468 446
469 // We don't care about Z component. 447 // We don't care about Z component.
470 TransformationMatrix matrixXYW = 448 TransformationMatrix matrixXYW =
471 TransformationMatrix(matrix.m11(), matrix.m12(), 0, matrix.m14(), 449 TransformationMatrix(matrix.m11(), matrix.m12(), 0, matrix.m14(),
472 matrix.m21(), matrix.m22(), 0, matrix.m24(), 450 matrix.m21(), matrix.m22(), 0, matrix.m24(),
473 matrix.m31(), matrix.m32(), 1, matrix.m34(), 451 matrix.m31(), matrix.m32(), 1, matrix.m34(),
474 matrix.m41(), matrix.m42(), 0, matrix.m44()); 452 matrix.m41(), matrix.m42(), 0, matrix.m44());
475 453
476 // Don't draw any tiles when matrix is not invertible. 454 // Don't draw any tiles when matrix is not invertible.
477 if (!matrixXYW.isInvertible()) 455 if (!matrixXYW.isInvertible())
478 return; 456 return;
479 457
480 TransformationMatrix inverse = matrixXYW.inverse(); 458 TransformationMatrix inverse = matrixXYW.inverse();
481 IntRect bounds(m_layerPosition, IntSize(m_tilingData.totalSizeX(),
482 m_tilingData.totalSizeY()));
483 459
484 // Include outer border texels in bounds. 460 GraphicsContext3D* context = layerRendererContext();
485 bounds.inflate(m_tilingData.borderTexels()); 461 GLC(context, context->useProgram(program->program()));
462 GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
463 GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
486 464
487 // Map bounds to device space. 465 // Map content rectangle to device space.
488 FloatQuad boundsQuad = matrix.mapQuad(FloatQuad(bounds)); 466 FloatQuad deviceQuad = matrix.mapQuad(FloatQuad(contentRect));
489 467
490 // Counter-clockwise? 468 // Counter-clockwise?
491 float sign = isCCW(boundsQuad) ? -1 : 1; 469 float sign = isCCW(deviceQuad) ? -1 : 1;
492 470
493 // Compute outer edges. 471 // Compute outer edges.
494 Edge leftEdge = computeEdge(boundsQuad.p4(), boundsQuad.p1(), sign); 472 Edge leftEdge = computeEdge(deviceQuad.p4(), deviceQuad.p1(), sign);
495 Edge rightEdge = computeEdge(boundsQuad.p2(), boundsQuad.p3(), sign); 473 Edge rightEdge = computeEdge(deviceQuad.p2(), deviceQuad.p3(), sign);
496 Edge topEdge = computeEdge(boundsQuad.p1(), boundsQuad.p2(), sign); 474 Edge topEdge = computeEdge(deviceQuad.p1(), deviceQuad.p2(), sign);
497 Edge bottomEdge = computeEdge(boundsQuad.p3(), boundsQuad.p4(), sign); 475 Edge bottomEdge = computeEdge(deviceQuad.p3(), deviceQuad.p4(), sign);
498 476
499 // Move outer edges to ensure that all partially covered pixels are 477 if (edgeLocation != -1) {
500 // processed. 478 // Move outer edges to ensure that all partially covered pixels are
501 float zDistance = m_tilingData.borderTexels() * 0.5f; 479 // processed.
502 leftEdge.move(0, 0, zDistance); 480 leftEdge.move(0, 0, 0.5f);
503 rightEdge.move(0, 0, zDistance); 481 rightEdge.move(0, 0, 0.5f);
504 topEdge.move(0, 0, zDistance); 482 topEdge.move(0, 0, 0.5f);
505 bottomEdge.move(0, 0, zDistance); 483 bottomEdge.move(0, 0, 0.5f);
506 484
507 GC3Dint filter = (m_tilingData.borderTexels() && !matrix.isIntegerTranslatio n()) ? GraphicsContext3D::LINEAR : GraphicsContext3D::NEAREST; 485 float edge[12];
486 edge[0] = leftEdge.x();
487 edge[1] = leftEdge.y();
488 edge[2] = leftEdge.z();
489 edge[3] = topEdge.x();
490 edge[4] = topEdge.y();
491 edge[5] = topEdge.z();
492 edge[6] = rightEdge.x();
493 edge[7] = rightEdge.y();
494 edge[8] = rightEdge.z();
495 edge[9] = bottomEdge.x();
496 edge[10] = bottomEdge.y();
497 edge[11] = bottomEdge.z();
498 GLC(context, context->uniform3fv(edgeLocation, edge, 4));
499 }
508 500
509 Edge prevEdgeY = topEdge; 501 Edge prevEdgeY = topEdge;
510 502
511 int left, top, right, bottom; 503 int left, top, right, bottom;
512 contentRectToTileIndices(contentRect, left, top, right, bottom); 504 contentRectToTileIndices(contentRect, left, top, right, bottom);
505 IntRect layerRect = contentRectToLayerRect(contentRect);
513 for (int j = top; j <= bottom; ++j) { 506 for (int j = top; j <= bottom; ++j) {
514 Edge prevEdgeX = leftEdge; 507 Edge prevEdgeX = leftEdge;
515 508
516 Edge edgeY = bottomEdge; 509 Edge edgeY = bottomEdge;
517 if (j < (m_tilingData.numTilesY() - 1)) { 510 if (j < (m_tilingData.numTilesY() - 1)) {
518 IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(0, j)); 511 IntRect tileRect = unionRect(m_tilingData.tileBounds(m_tilingData.ti leIndex(0, j)), m_tilingData.tileBounds(m_tilingData.tileIndex(m_tilingData.numT ilesX() - 1, j)));
512 tileRect.intersect(layerRect);
513
514 // Skip empty rows.
515 if (tileRect.isEmpty())
516 continue;
517
519 tileRect.move(m_layerPosition.x(), m_layerPosition.y()); 518 tileRect.move(m_layerPosition.x(), m_layerPosition.y());
520 519
521 FloatPoint p1(tileRect.maxX(), tileRect.maxY()); 520 FloatPoint p1(tileRect.maxX(), tileRect.maxY());
522 FloatPoint p2(tileRect.x(), tileRect.maxY()); 521 FloatPoint p2(tileRect.x(), tileRect.maxY());
523 522
524 // Map points to device space. 523 // Map points to device space.
525 p1 = matrix.mapPoint(p1); 524 p1 = matrix.mapPoint(p1);
526 p2 = matrix.mapPoint(p2); 525 p2 = matrix.mapPoint(p2);
527 526
528 // Compute horizontal edge. 527 // Compute horizontal edge.
529 edgeY = computeEdge(p1, p2, sign); 528 edgeY = computeEdge(p1, p2, sign);
530 } 529 }
531 530
532 for (int i = left; i <= right; ++i) { 531 for (int i = left; i <= right; ++i) {
533 Tile* tile = tileAt(i, j); 532 Tile* tile = tileAt(i, j);
534 if (!tile) 533 if (!tile)
535 continue; 534 continue;
536 535
537 ASSERT(tile->texture()->isReserved()); 536 ASSERT(tile->texture()->isReserved());
538 537
539 tile->texture()->bindTexture(); 538 tile->texture()->bindTexture();
540 GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, G raphicsContext3D::TEXTURE_MIN_FILTER, filter));
541 GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, G raphicsContext3D::TEXTURE_MAG_FILTER, filter));
542 539
543 // Don't use tileContentRect here, as that contains the full 540 // Don't use tileContentRect here, as that contains the full
544 // rect with border texels which shouldn't be drawn. 541 // rect with border texels which shouldn't be drawn.
545 IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(ti le->i(), tile->j())); 542 IntRect tileRect = m_tilingData.tileBounds(m_tilingData.tileIndex(ti le->i(), tile->j()));
543 IntRect displayRect = tileRect;
544 tileRect.intersect(layerRect);
545
546 // Keep track of how the top left has moved, so the texture can be
547 // offset the same amount.
548 IntSize displayOffset = tileRect.minXMinYCorner() - displayRect.minX MinYCorner();
549
550 // Skip empty tiles.
551 if (tileRect.isEmpty())
552 continue;
553
546 tileRect.move(m_layerPosition.x(), m_layerPosition.y()); 554 tileRect.move(m_layerPosition.x(), m_layerPosition.y());
547 555
548 IntPoint texOffset = m_tilingData.textureOffset(); 556 FloatRect clampRect(tileRect);
549 IntRect texRect = tileTexRect(tile); 557 // Clamp texture coordinates to avoid sampling outside the layer
550 float tileWidth = static_cast<float>(texRect.width()); 558 // by deflating the tile region half a texel or half a texel
551 float tileHeight = static_cast<float>(texRect.height()); 559 // minus epsilon for one pixel layers. The resulting clamp region
552 float texTranslateX = (texOffset.x() - tileRect.x()) / tileWidth; 560 // is mapped to the unit square by the vertex shader and mapped
553 float texTranslateY = (texOffset.y() - tileRect.y()) / tileHeight; 561 // back to normalized texture coordinates by the fragment shader
554 float texScaleX = tileRect.width() / tileWidth; 562 // after being clamped to 0-1 range.
555 float texScaleY = tileRect.height() / tileHeight; 563 const float epsilon = 1 / 1024.0f;
564 float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
565 float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
566 clampRect.inflateX(-clampX);
567 clampRect.inflateY(-clampY);
568 FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileR ect).minXMinYCorner();
569
570 FloatPoint texOffset = m_tilingData.textureOffset(tile->i(), tile->j ()) + clampOffset + FloatSize(displayOffset);
571 float tileWidth = static_cast<float>(m_tileSize.width());
572 float tileHeight = static_cast<float>(m_tileSize.height());
573
574 // Map clamping rectangle to unit square.
575 float vertexTexTranslateX = -clampRect.x() / clampRect.width();
576 float vertexTexTranslateY = -clampRect.y() / clampRect.height();
577 float vertexTexScaleX = tileRect.width() / clampRect.width();
578 float vertexTexScaleY = tileRect.height() / clampRect.height();
579
580 // Map to normalized texture coordinates.
581 float fragmentTexTranslateX = texOffset.x() / tileWidth;
582 float fragmentTexTranslateY = texOffset.y() / tileHeight;
583 float fragmentTexScaleX = clampRect.width() / tileWidth;
584 float fragmentTexScaleY = clampRect.height() / tileHeight;
585
556 // OpenGL coordinate system is bottom-up. 586 // OpenGL coordinate system is bottom-up.
557 // If tile texture is top-down, we need to flip the texture coordina tes. 587 // If tile texture is top-down, we need to flip the texture coordina tes.
558 if (m_textureOrientation == LayerTextureUpdater::TopDownOrientation) { 588 if (m_textureOrientation == LayerTextureUpdater::TopDownOrientation) {
559 texTranslateY = 1.0 - texTranslateY; 589 fragmentTexTranslateY = 1.0 - fragmentTexTranslateY;
560 texScaleY *= -1.0; 590 fragmentTexScaleY *= -1.0;
561 } 591 }
562 592
563 Edge edgeX = rightEdge; 593 Edge edgeX = rightEdge;
564 if (i < (m_tilingData.numTilesX() - 1)) { 594 if (i < (m_tilingData.numTilesX() - 1)) {
565 FloatPoint p1(tileRect.maxX(), tileRect.y()); 595 FloatPoint p1(tileRect.maxX(), tileRect.y());
566 FloatPoint p2(tileRect.maxX(), tileRect.maxY()); 596 FloatPoint p2(tileRect.maxX(), tileRect.maxY());
567 597
568 // Map points to device space. 598 // Map points to device space.
569 p1 = matrix.mapPoint(p1); 599 p1 = matrix.mapPoint(p1);
570 p2 = matrix.mapPoint(p2); 600 p2 = matrix.mapPoint(p2);
571 601
572 // Compute vertical edge. 602 // Compute vertical edge.
573 edgeX = computeEdge(p1, p2, sign); 603 edgeX = computeEdge(p1, p2, sign);
574 } 604 }
575 605
576 // Create device space quad. 606 // Create device space quad.
577 FloatQuad deviceQuad(intersect(edgeY, prevEdgeX), 607 FloatQuad deviceQuad(intersect(edgeY, prevEdgeX),
578 intersect(prevEdgeX, prevEdgeY), 608 intersect(prevEdgeX, prevEdgeY),
579 intersect(prevEdgeY, edgeX), 609 intersect(prevEdgeY, edgeX),
580 intersect(edgeX, edgeY)); 610 intersect(edgeX, edgeY));
581 611
582 // Map quad to layer space. 612 // Map quad to layer space.
583 FloatQuad quad = inverse.mapQuad(deviceQuad); 613 FloatQuad quad = inverse.mapQuad(deviceQuad);
584 614
585 // Normalize to tileRect. 615 // Normalize to tileRect.
586 quad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height()); 616 quad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
587 617
588 drawTexturedQuad(context, quad, layerRenderer()->projectionMatrix(), matrix, tileRect.width(), tileRect.height(), opacity, texTranslateX, texTransla teY, texScaleX, texScaleY, program); 618 if (fragmentTexTransformLocation == -1) {
619 // Move fragment shader transform to vertex shader. We can do
620 // this while still producing correct results as
621 // fragmentTexTransformLocation should always be non-negative
622 // when tiles are transformed in a way that could result in
623 // sampling outside the layer.
624 vertexTexScaleX *= fragmentTexScaleX;
625 vertexTexScaleY *= fragmentTexScaleY;
626 vertexTexTranslateX *= fragmentTexScaleX;
627 vertexTexTranslateY *= fragmentTexScaleY;
628 vertexTexTranslateX += fragmentTexTranslateX;
629 vertexTexTranslateY += fragmentTexTranslateY;
630 } else
631 GLC(context, context->uniform4f(fragmentTexTransformLocation, fr agmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY ));
632
633 GLC(context, context->uniform4f(program->vertexShader().vertexTexTra nsformLocation(), vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, ver texTexScaleY));
634
635 float point[8];
636 point[0] = quad.p1().x();
637 point[1] = quad.p1().y();
638 point[2] = quad.p2().x();
639 point[3] = quad.p2().y();
640 point[4] = quad.p3().x();
641 point[5] = quad.p3().y();
642 point[6] = quad.p4().x();
643 point[7] = quad.p4().y();
644 GLC(context, context->uniform2fv(program->vertexShader().pointLocati on(), point, 4));
645
646 LayerChromium::drawTexturedQuad(context, layerRenderer()->projection Matrix(), globalTransform,
647 tileRect.width(), tileRect.height(), opacity,
648 program->vertexShader().matrixLocati on(),
649 program->fragmentShader().alphaLocat ion());
589 650
590 prevEdgeX = edgeX; 651 prevEdgeX = edgeX;
652 // Reverse direction.
653 prevEdgeX.scale(-1, -1, -1);
591 } 654 }
592 655
593 prevEdgeY = edgeY; 656 prevEdgeY = edgeY;
657 // Reverse direction.
658 prevEdgeY.scale(-1, -1, -1);
594 } 659 }
595 } 660 }
596 661
597 template <class T>
598 void LayerTilerChromium::drawTexturedQuad(GraphicsContext3D* context, const Floa tQuad& quad, const TransformationMatrix& projectionMatrix, const TransformationM atrix& drawMatrix,
599 float width, float height, float opaci ty,
600 float texTranslateX, float texTranslat eY,
601 float texScaleX, float texScaleY,
602 const T* program)
603 {
604 static float glMatrix[16];
605
606 TransformationMatrix renderMatrix = drawMatrix;
607
608 // Apply a scaling factor to size the quad from 1x1 to its intended size.
609 renderMatrix.scale3d(width, height, 1);
610
611 // Apply the projection matrix before sending the transform over to the shad er.
612 LayerChromium::toGLMatrix(&glMatrix[0], projectionMatrix * renderMatrix);
613
614 GLC(context, context->uniformMatrix4fv(program->vertexShader().matrixLocatio n(), false, &glMatrix[0], 1));
615
616 GLC(context, context->uniform1f(program->fragmentShader().alphaLocation(), o pacity));
617
618 GLC(context, context->uniform4f(program->vertexShader().texTransformLocation (),
619 texTranslateX, texTranslateY, texScaleX, texScaleY));
620
621 float point[8];
622 point[0] = quad.p1().x();
623 point[1] = quad.p1().y();
624 point[2] = quad.p2().x();
625 point[3] = quad.p2().y();
626 point[4] = quad.p3().x();
627 point[5] = quad.p3().y();
628 point[6] = quad.p4().x();
629 point[7] = quad.p4().y();
630 GLC(context, context->uniform2fv(program->vertexShader().pointLocation(), po int, 4));
631
632 GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, Graphics Context3D::UNSIGNED_SHORT, 0));
633 }
634
635 } // namespace WebCore 662 } // namespace WebCore
636 663
637 #endif // USE(ACCELERATED_COMPOSITING) 664 #endif // USE(ACCELERATED_COMPOSITING)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698