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

Side by Side Diff: cc/gl_renderer.cc

Issue 10984053: cc: Use ui/gfx geometry types for the CCRenderPass and CCDrawQuad classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « cc/gl_renderer.h ('k') | cc/io_surface_draw_quad.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 The Chromium Authors. All rights reserved. 1 // Copyright 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 6
7 #include "CCRendererGL.h" 7 #include "CCRendererGL.h"
8 8
9 #include "CCDamageTracker.h" 9 #include "CCDamageTracker.h"
10 #include "CCLayerQuad.h" 10 #include "CCLayerQuad.h"
(...skipping 13 matching lines...) Expand all
24 #include "base/string_util.h" 24 #include "base/string_util.h"
25 #include "cc/geometry_binding.h" 25 #include "cc/geometry_binding.h"
26 #include "cc/platform_color.h" 26 #include "cc/platform_color.h"
27 #include "cc/single_thread_proxy.h" 27 #include "cc/single_thread_proxy.h"
28 #include "cc/stream_video_draw_quad.h" 28 #include "cc/stream_video_draw_quad.h"
29 #include "cc/texture_draw_quad.h" 29 #include "cc/texture_draw_quad.h"
30 #include "third_party/khronos/GLES2/gl2.h" 30 #include "third_party/khronos/GLES2/gl2.h"
31 #include "third_party/khronos/GLES2/gl2ext.h" 31 #include "third_party/khronos/GLES2/gl2ext.h"
32 #include "third_party/skia/include/core/SkBitmap.h" 32 #include "third_party/skia/include/core/SkBitmap.h"
33 #include "third_party/skia/include/core/SkColor.h" 33 #include "third_party/skia/include/core/SkColor.h"
34 #include "ui/gfx/rect_conversions.h"
34 #include <public/WebGraphicsContext3D.h> 35 #include <public/WebGraphicsContext3D.h>
35 #include <public/WebSharedGraphicsContext3D.h> 36 #include <public/WebSharedGraphicsContext3D.h>
36 #include <public/WebVideoFrame.h> 37 #include <public/WebVideoFrame.h>
37 #include <set> 38 #include <set>
38 #include <string> 39 #include <string>
39 #include <vector> 40 #include <vector>
40 #include <wtf/CurrentTime.h> 41 #include <wtf/CurrentTime.h>
41 42
42 using namespace std; 43 using namespace std;
43 using WebKit::WebGraphicsContext3D; 44 using WebKit::WebGraphicsContext3D;
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 if (frame.currentRenderPass->hasTransparentBackground()) 203 if (frame.currentRenderPass->hasTransparentBackground())
203 #endif 204 #endif
204 m_context->clear(GL_COLOR_BUFFER_BIT); 205 m_context->clear(GL_COLOR_BUFFER_BIT);
205 } 206 }
206 207
207 void CCRendererGL::beginDrawingFrame(DrawingFrame& frame) 208 void CCRendererGL::beginDrawingFrame(DrawingFrame& frame)
208 { 209 {
209 // FIXME: Remove this once framebuffer is automatically recreated on first u se 210 // FIXME: Remove this once framebuffer is automatically recreated on first u se
210 ensureFramebuffer(); 211 ensureFramebuffer();
211 212
212 if (viewportSize().isEmpty()) 213 if (viewportSize().IsEmpty())
213 return; 214 return;
214 215
215 TRACE_EVENT0("cc", "CCRendererGL::drawLayers"); 216 TRACE_EVENT0("cc", "CCRendererGL::drawLayers");
216 if (m_isViewportChanged) { 217 if (m_isViewportChanged) {
217 // Only reshape when we know we are going to draw. Otherwise, the reshap e 218 // Only reshape when we know we are going to draw. Otherwise, the reshap e
218 // can leave the window at the wrong size if we never draw and the prope r 219 // can leave the window at the wrong size if we never draw and the prope r
219 // viewport size is never set. 220 // viewport size is never set.
220 m_isViewportChanged = false; 221 m_isViewportChanged = false;
221 m_context->reshape(viewportWidth(), viewportHeight()); 222 m_context->reshape(viewportWidth(), viewportHeight());
222 } 223 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 const TileCheckerboardProgram* program = tileCheckerboardProgram(); 285 const TileCheckerboardProgram* program = tileCheckerboardProgram();
285 DCHECK(program && program->initialized()); 286 DCHECK(program && program->initialized());
286 GLC(context(), context()->useProgram(program->program())); 287 GLC(context(), context()->useProgram(program->program()));
287 288
288 SkColor color = quad->color(); 289 SkColor color = quad->color();
289 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation( ), SkColorGetR(color) / 255.0, SkColorGetG(color) / 255.0, SkColorGetB(color) / 255.0, 1)); 290 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation( ), SkColorGetR(color) / 255.0, SkColorGetG(color) / 255.0, SkColorGetB(color) / 255.0, 1));
290 291
291 const int checkerboardWidth = 16; 292 const int checkerboardWidth = 16;
292 float frequency = 1.0 / checkerboardWidth; 293 float frequency = 1.0 / checkerboardWidth;
293 294
294 IntRect tileRect = quad->quadRect(); 295 gfx::Rect tileRect = quad->quadRect();
295 float texOffsetX = tileRect.x() % checkerboardWidth; 296 float texOffsetX = tileRect.x() % checkerboardWidth;
296 float texOffsetY = tileRect.y() % checkerboardWidth; 297 float texOffsetY = tileRect.y() % checkerboardWidth;
297 float texScaleX = tileRect.width(); 298 float texScaleX = tileRect.width();
298 float texScaleY = tileRect.height(); 299 float texScaleY = tileRect.height();
299 GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLo cation(), texOffsetX, texOffsetY, texScaleX, texScaleY)); 300 GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLo cation(), texOffsetX, texOffsetY, texScaleX, texScaleY));
300 301
301 GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocat ion(), frequency)); 302 GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocat ion(), frequency));
302 303
303 setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()) ; 304 setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation()) ;
304 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->ve rtexShader().matrixLocation()); 305 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->ve rtexShader().matrixLocation());
305 } 306 }
306 307
307 void CCRendererGL::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugB orderDrawQuad* quad) 308 void CCRendererGL::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugB orderDrawQuad* quad)
308 { 309 {
309 static float glMatrix[16]; 310 static float glMatrix[16];
310 const SolidColorProgram* program = solidColorProgram(); 311 const SolidColorProgram* program = solidColorProgram();
311 DCHECK(program && program->initialized()); 312 DCHECK(program && program->initialized());
312 GLC(context(), context()->useProgram(program->program())); 313 GLC(context(), context()->useProgram(program->program()));
313 314
314 // Use the full quadRect for debug quads to not move the edges based on part ial swaps. 315 // Use the full quadRect for debug quads to not move the edges based on part ial swaps.
315 const IntRect& layerRect = quad->quadRect(); 316 const gfx::Rect& layerRect = quad->quadRect();
316 WebTransformationMatrix renderMatrix = quad->quadTransform(); 317 WebTransformationMatrix renderMatrix = quad->quadTransform();
317 renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerR ect.height() + layerRect.y()); 318 renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerR ect.height() + layerRect.y());
318 renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height()); 319 renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height());
319 CCRendererGL::toGLMatrix(&glMatrix[0], frame.projectionMatrix * renderMatrix ); 320 CCRendererGL::toGLMatrix(&glMatrix[0], frame.projectionMatrix * renderMatrix );
320 GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLoc ation(), 1, false, &glMatrix[0])); 321 GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLoc ation(), 1, false, &glMatrix[0]));
321 322
322 SkColor color = quad->color(); 323 SkColor color = quad->color();
323 float alpha = SkColorGetA(color) / 255.0; 324 float alpha = SkColorGetA(color) / 255.0;
324 325
325 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation( ), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, ( SkColorGetB(color) / 255.0) * alpha, alpha)); 326 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation( ), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, ( SkColorGetB(color) / 255.0) * alpha, alpha));
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 if (filters.isEmpty()) 370 if (filters.isEmpty())
370 return scoped_ptr<CCScopedTexture>(); 371 return scoped_ptr<CCScopedTexture>();
371 372
372 // FIXME: We only allow background filters on an opaque render surface becau se other surfaces may contain 373 // FIXME: We only allow background filters on an opaque render surface becau se other surfaces may contain
373 // translucent pixels, and the contents behind those translucent pixels woul dn't have the filter applied. 374 // translucent pixels, and the contents behind those translucent pixels woul dn't have the filter applied.
374 if (frame.currentRenderPass->hasTransparentBackground()) 375 if (frame.currentRenderPass->hasTransparentBackground())
375 return scoped_ptr<CCScopedTexture>(); 376 return scoped_ptr<CCScopedTexture>();
376 DCHECK(!frame.currentTexture); 377 DCHECK(!frame.currentTexture);
377 378
378 // FIXME: Do a single readback for both the surface and replica and cache th e filtered results (once filter textures are not reused). 379 // FIXME: Do a single readback for both the surface and replica and cache th e filtered results (once filter textures are not reused).
379 IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDev iceTransform, sharedGeometryQuad().boundingBox())); 380 gfx::Rect deviceRect = gfx::ToEnclosingRect(CCMathUtil::mapClippedRect(conte ntsDeviceTransform, sharedGeometryQuad().boundingBox()));
380 381
381 int top, right, bottom, left; 382 int top, right, bottom, left;
382 filters.getOutsets(top, right, bottom, left); 383 filters.getOutsets(top, right, bottom, left);
383 deviceRect.move(-left, -top); 384 deviceRect.Inset(-left, -top, -right, -bottom);
384 deviceRect.expand(left + right, top + bottom);
385 385
386 deviceRect.intersect(frame.currentRenderPass->outputRect()); 386 deviceRect = deviceRect.Intersect(frame.currentRenderPass->outputRect());
387 387
388 scoped_ptr<CCScopedTexture> deviceBackgroundTexture = CCScopedTexture::creat e(m_resourceProvider); 388 scoped_ptr<CCScopedTexture> deviceBackgroundTexture = CCScopedTexture::creat e(m_resourceProvider);
389 if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect)) 389 if (!getFramebufferTexture(deviceBackgroundTexture.get(), cc::IntRect(device Rect)))
390 return scoped_ptr<CCScopedTexture>(); 390 return scoped_ptr<CCScopedTexture>();
391 391
392 SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgr oundTexture.get()); 392 SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgr oundTexture.get());
393 if (!filteredDeviceBackground.getTexture()) 393 if (!filteredDeviceBackground.getTexture())
394 return scoped_ptr<CCScopedTexture>(); 394 return scoped_ptr<CCScopedTexture>();
395 395
396 GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.g etTexture()); 396 GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.g etTexture());
397 int filteredDeviceBackgroundTextureId = texture->getTextureHandle(); 397 int filteredDeviceBackgroundTextureId = texture->getTextureHandle();
398 398
399 scoped_ptr<CCScopedTexture> backgroundTexture = CCScopedTexture::create(m_re sourceProvider); 399 scoped_ptr<CCScopedTexture> backgroundTexture = CCScopedTexture::create(m_re sourceProvider);
400 if (!backgroundTexture->allocate(CCRenderer::ImplPool, quad->quadRect().size (), GL_RGBA, CCResourceProvider::TextureUsageFramebuffer)) 400 if (!backgroundTexture->allocate(CCRenderer::ImplPool, cc::IntSize(quad->qua dRect().size()), GL_RGBA, CCResourceProvider::TextureUsageFramebuffer))
401 return scoped_ptr<CCScopedTexture>(); 401 return scoped_ptr<CCScopedTexture>();
402 402
403 const CCRenderPass* targetRenderPass = frame.currentRenderPass; 403 const CCRenderPass* targetRenderPass = frame.currentRenderPass;
404 bool usingBackgroundTexture = useScopedTexture(frame, backgroundTexture.get( ), quad->quadRect()); 404 bool usingBackgroundTexture = useScopedTexture(frame, backgroundTexture.get( ), quad->quadRect());
405 405
406 if (usingBackgroundTexture) { 406 if (usingBackgroundTexture) {
407 // Copy the readback pixels from device to the background texture for th e surface. 407 // Copy the readback pixels from device to the background texture for th e surface.
408 WebTransformationMatrix deviceToFramebufferTransform; 408 WebTransformationMatrix deviceToFramebufferTransform;
409 deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, q uad->quadRect().height() / 2.0); 409 deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, q uad->quadRect().height() / 2.0);
410 deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->qua dRect().height(), 1); 410 deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->qua dRect().height(), 1);
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 uniforms.pointLocation = program->vertexShader().pointLocation(); 593 uniforms.pointLocation = program->vertexShader().pointLocation();
594 594
595 uniforms.samplerLocation = program->fragmentShader().samplerLocation(); 595 uniforms.samplerLocation = program->fragmentShader().samplerLocation();
596 uniforms.alphaLocation = program->fragmentShader().alphaLocation(); 596 uniforms.alphaLocation = program->fragmentShader().alphaLocation();
597 uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTe xTransformLocation(); 597 uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTe xTransformLocation();
598 uniforms.edgeLocation = program->fragmentShader().edgeLocation(); 598 uniforms.edgeLocation = program->fragmentShader().edgeLocation();
599 } 599 }
600 600
601 void CCRendererGL::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad) 601 void CCRendererGL::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad)
602 { 602 {
603 IntRect tileRect = quad->quadVisibleRect(); 603 gfx::Rect tileRect = quad->quadVisibleRect();
604 604
605 FloatRect clampRect(tileRect); 605 gfx::RectF clampRect(tileRect);
606 // Clamp texture coordinates to avoid sampling outside the layer 606 // Clamp texture coordinates to avoid sampling outside the layer
607 // by deflating the tile region half a texel or half a texel 607 // by deflating the tile region half a texel or half a texel
608 // minus epsilon for one pixel layers. The resulting clamp region 608 // minus epsilon for one pixel layers. The resulting clamp region
609 // is mapped to the unit square by the vertex shader and mapped 609 // is mapped to the unit square by the vertex shader and mapped
610 // back to normalized texture coordinates by the fragment shader 610 // back to normalized texture coordinates by the fragment shader
611 // after being clamped to 0-1 range. 611 // after being clamped to 0-1 range.
612 const float epsilon = 1 / 1024.0f; 612 const float epsilon = 1 / 1024.0f;
613 float clampX = min(0.5, clampRect.width() / 2.0 - epsilon); 613 float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
614 float clampY = min(0.5, clampRect.height() / 2.0 - epsilon); 614 float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
615 clampRect.inflateX(-clampX); 615 clampRect.Inset(clampX, clampY, clampX, clampY);
616 clampRect.inflateY(-clampY); 616 gfx::PointF clampOffset = clampRect.origin() - tileRect.origin();
617 FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).min XMinYCorner();
618 617
619 FloatPoint textureOffset = quad->textureOffset() + clampOffset + 618 gfx::PointF textureOffset = quad->textureOffset() + clampOffset +
620 IntPoint(tileRect.location() - quad->quadRect().l ocation()); 619 (tileRect.origin() - quad->quadRect().origin());
621 620
622 // Map clamping rectangle to unit square. 621 // Map clamping rectangle to unit square.
623 float vertexTexTranslateX = -clampRect.x() / clampRect.width(); 622 float vertexTexTranslateX = -clampRect.x() / clampRect.width();
624 float vertexTexTranslateY = -clampRect.y() / clampRect.height(); 623 float vertexTexTranslateY = -clampRect.y() / clampRect.height();
625 float vertexTexScaleX = tileRect.width() / clampRect.width(); 624 float vertexTexScaleX = tileRect.width() / clampRect.width();
626 float vertexTexScaleY = tileRect.height() / clampRect.height(); 625 float vertexTexScaleY = tileRect.height() / clampRect.height();
627 626
628 // Map to normalized texture coordinates. 627 // Map to normalized texture coordinates.
629 const IntSize& textureSize = quad->textureSize(); 628 const gfx::Size& textureSize = quad->textureSize();
630 float fragmentTexTranslateX = textureOffset.x() / textureSize.width(); 629 float fragmentTexTranslateX = textureOffset.x() / textureSize.width();
631 float fragmentTexTranslateY = textureOffset.y() / textureSize.height(); 630 float fragmentTexTranslateY = textureOffset.y() / textureSize.height();
632 float fragmentTexScaleX = clampRect.width() / textureSize.width(); 631 float fragmentTexScaleX = clampRect.width() / textureSize.width();
633 float fragmentTexScaleY = clampRect.height() / textureSize.height(); 632 float fragmentTexScaleY = clampRect.height() / textureSize.height();
634 633
635 634
636 FloatQuad localQuad; 635 FloatQuad localQuad;
637 WebTransformationMatrix deviceTransform = WebTransformationMatrix(frame.wind owMatrix * frame.projectionMatrix * quad->quadTransform()).to2dTransform(); 636 WebTransformationMatrix deviceTransform = WebTransformationMatrix(frame.wind owMatrix * frame.projectionMatrix * quad->quadTransform()).to2dTransform();
638 if (!deviceTransform.isInvertible()) 637 if (!deviceTransform.isInvertible())
639 return; 638 return;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 deviceLayerEdges.inflateAntiAliasingDistance(); 680 deviceLayerEdges.inflateAntiAliasingDistance();
682 681
683 float edge[24]; 682 float edge[24];
684 deviceLayerEdges.toFloatArray(edge); 683 deviceLayerEdges.toFloatArray(edge);
685 deviceLayerBounds.toFloatArray(&edge[12]); 684 deviceLayerBounds.toFloatArray(&edge[12]);
686 GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge)); 685 GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));
687 686
688 GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY)); 687 GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
689 GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocatio n, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexS caleY)); 688 GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocatio n, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexS caleY));
690 689
691 FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY()); 690 FloatPoint bottomRight(tileRect.right(), tileRect.bottom());
692 FloatPoint bottomLeft(tileRect.x(), tileRect.maxY()); 691 FloatPoint bottomLeft(tileRect.x(), tileRect.bottom());
693 FloatPoint topLeft(tileRect.x(), tileRect.y()); 692 FloatPoint topLeft(tileRect.x(), tileRect.y());
694 FloatPoint topRight(tileRect.maxX(), tileRect.y()); 693 FloatPoint topRight(tileRect.right(), tileRect.y());
695 694
696 // Map points to device space. 695 // Map points to device space.
697 bottomRight = CCMathUtil::mapPoint(deviceTransform, bottomRight, clipped ); 696 bottomRight = CCMathUtil::mapPoint(deviceTransform, bottomRight, clipped );
698 DCHECK(!clipped); 697 DCHECK(!clipped);
699 bottomLeft = CCMathUtil::mapPoint(deviceTransform, bottomLeft, clipped); 698 bottomLeft = CCMathUtil::mapPoint(deviceTransform, bottomLeft, clipped);
700 DCHECK(!clipped); 699 DCHECK(!clipped);
701 topLeft = CCMathUtil::mapPoint(deviceTransform, topLeft, clipped); 700 topLeft = CCMathUtil::mapPoint(deviceTransform, topLeft, clipped);
702 DCHECK(!clipped); 701 DCHECK(!clipped);
703 topRight = CCMathUtil::mapPoint(deviceTransform, topRight, clipped); 702 topRight = CCMathUtil::mapPoint(deviceTransform, topRight, clipped);
704 DCHECK(!clipped); 703 DCHECK(!clipped);
705 704
706 CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft); 705 CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
707 CCLayerQuad::Edge leftEdge(bottomLeft, topLeft); 706 CCLayerQuad::Edge leftEdge(bottomLeft, topLeft);
708 CCLayerQuad::Edge topEdge(topLeft, topRight); 707 CCLayerQuad::Edge topEdge(topLeft, topRight);
709 CCLayerQuad::Edge rightEdge(topRight, bottomRight); 708 CCLayerQuad::Edge rightEdge(topRight, bottomRight);
710 709
711 // Only apply anti-aliasing to edges not clipped by culling or scissorin g. 710 // Only apply anti-aliasing to edges not clipped by culling or scissorin g.
712 if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y()) 711 if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
713 topEdge = deviceLayerEdges.top(); 712 topEdge = deviceLayerEdges.top();
714 if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x()) 713 if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
715 leftEdge = deviceLayerEdges.left(); 714 leftEdge = deviceLayerEdges.left();
716 if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX()) 715 if (quad->rightEdgeAA() && tileRect.right() == quad->quadRect().right())
717 rightEdge = deviceLayerEdges.right(); 716 rightEdge = deviceLayerEdges.right();
718 if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY()) 717 if (quad->bottomEdgeAA() && tileRect.bottom() == quad->quadRect().bottom ())
719 bottomEdge = deviceLayerEdges.bottom(); 718 bottomEdge = deviceLayerEdges.bottom();
720 719
721 float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1; 720 float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
722 bottomEdge.scale(sign); 721 bottomEdge.scale(sign);
723 leftEdge.scale(sign); 722 leftEdge.scale(sign);
724 topEdge.scale(sign); 723 topEdge.scale(sign);
725 rightEdge.scale(sign); 724 rightEdge.scale(sign);
726 725
727 // Create device space quad. 726 // Create device space quad.
728 CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge); 727 CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
(...skipping 25 matching lines...) Expand all
754 localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height()); 753 localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
755 754
756 setShaderOpacity(quad->opacity(), uniforms.alphaLocation); 755 setShaderOpacity(quad->opacity(), uniforms.alphaLocation);
757 setShaderFloatQuad(localQuad, uniforms.pointLocation); 756 setShaderFloatQuad(localQuad, uniforms.pointLocation);
758 757
759 // The tile quad shader behaves differently compared to all other shaders. 758 // The tile quad shader behaves differently compared to all other shaders.
760 // The transform and vertex data are used to figure out the extents that the 759 // The transform and vertex data are used to figure out the extents that the
761 // un-antialiased quad should have and which vertex this is and the float 760 // un-antialiased quad should have and which vertex this is and the float
762 // quad passed in via uniform is the actual geometry that gets used to draw 761 // quad passed in via uniform is the actual geometry that gets used to draw
763 // it. This is why this centered rect is used and not the original quadRect. 762 // it. This is why this centered rect is used and not the original quadRect.
764 FloatRect centeredRect(FloatPoint(-0.5 * tileRect.width(), -0.5 * tileRect.h eight()), tileRect.size()); 763 gfx::RectF centeredRect(gfx::PointF(-0.5 * tileRect.width(), -0.5 * tileRect .height()), tileRect.size());
765 drawQuadGeometry(frame, quad->quadTransform(), centeredRect, uniforms.matrix Location); 764 drawQuadGeometry(frame, quad->quadTransform(), centeredRect, uniforms.matrix Location);
766 } 765 }
767 766
768 void CCRendererGL::drawYUVVideoQuad(const DrawingFrame& frame, const CCYUVVideoD rawQuad* quad) 767 void CCRendererGL::drawYUVVideoQuad(const DrawingFrame& frame, const CCYUVVideoD rawQuad* quad)
769 { 768 {
770 const VideoYUVProgram* program = videoYUVProgram(); 769 const VideoYUVProgram* program = videoYUVProgram();
771 DCHECK(program && program->initialized()); 770 DCHECK(program && program->initialized());
772 771
773 const CCVideoLayerImpl::FramePlane& yPlane = quad->yPlane(); 772 const CCVideoLayerImpl::FramePlane& yPlane = quad->yPlane();
774 const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane(); 773 const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane();
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 { 873 {
875 DCHECK(CCProxy::isImplThread()); 874 DCHECK(CCProxy::isImplThread());
876 875
877 TexTransformTextureProgramBinding binding; 876 TexTransformTextureProgramBinding binding;
878 if (quad->flipped()) 877 if (quad->flipped())
879 binding.set(textureProgramFlip()); 878 binding.set(textureProgramFlip());
880 else 879 else
881 binding.set(textureProgram()); 880 binding.set(textureProgram());
882 GLC(context(), context()->useProgram(binding.programId)); 881 GLC(context(), context()->useProgram(binding.programId));
883 GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); 882 GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
884 const FloatRect& uvRect = quad->uvRect(); 883 const gfx::RectF& uvRect = quad->uvRect();
885 GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x() , uvRect.y(), uvRect.width(), uvRect.height())); 884 GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x() , uvRect.y(), uvRect.width(), uvRect.height()));
886 885
887 GLC(context(), context()->activeTexture(GL_TEXTURE0)); 886 GLC(context(), context()->activeTexture(GL_TEXTURE0));
888 CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, qu ad->resourceId()); 887 CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, qu ad->resourceId());
889 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, quadResourceLock.textur eId())); 888 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, quadResourceLock.textur eId()));
890 889
891 // FIXME: setting the texture parameters every time is redundant. Move this code somewhere 890 // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
892 // where it will only happen once per texture. 891 // where it will only happen once per texture.
893 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR)); 892 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR));
894 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR)); 893 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR));
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
932 931
933 setShaderOpacity(quad->opacity(), binding.alphaLocation); 932 setShaderOpacity(quad->opacity(), binding.alphaLocation);
934 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.mat rixLocation); 933 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.mat rixLocation);
935 934
936 GLC(context(), context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, 0)); 935 GLC(context(), context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, 0));
937 } 936 }
938 937
939 void CCRendererGL::finishDrawingFrame(DrawingFrame& frame) 938 void CCRendererGL::finishDrawingFrame(DrawingFrame& frame)
940 { 939 {
941 m_currentFramebufferLock.reset(); 940 m_currentFramebufferLock.reset();
942 m_swapBufferRect.unite(enclosingIntRect(frame.rootDamageRect)); 941 m_swapBufferRect = m_swapBufferRect.Union(gfx::ToEnclosingRect(frame.rootDam ageRect));
943 942
944 GLC(m_context, m_context->disable(GL_SCISSOR_TEST)); 943 GLC(m_context, m_context->disable(GL_SCISSOR_TEST));
945 GLC(m_context, m_context->disable(GL_BLEND)); 944 GLC(m_context, m_context->disable(GL_BLEND));
946 } 945 }
947 946
948 bool CCRendererGL::flippedFramebuffer() const 947 bool CCRendererGL::flippedFramebuffer() const
949 { 948 {
950 return true; 949 return true;
951 } 950 }
952 951
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 point[7] = quad.p4().y(); 985 point[7] = quad.p4().y();
987 GLC(m_context, m_context->uniform2fv(quadLocation, 4, point)); 986 GLC(m_context, m_context->uniform2fv(quadLocation, 4, point));
988 } 987 }
989 988
990 void CCRendererGL::setShaderOpacity(float opacity, int alphaLocation) 989 void CCRendererGL::setShaderOpacity(float opacity, int alphaLocation)
991 { 990 {
992 if (alphaLocation != -1) 991 if (alphaLocation != -1)
993 GLC(m_context, m_context->uniform1f(alphaLocation, opacity)); 992 GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
994 } 993 }
995 994
996 void CCRendererGL::drawQuadGeometry(const DrawingFrame& frame, const WebKit::Web TransformationMatrix& drawTransform, const FloatRect& quadRect, int matrixLocati on) 995 void CCRendererGL::drawQuadGeometry(const DrawingFrame& frame, const WebKit::Web TransformationMatrix& drawTransform, const gfx::RectF& quadRect, int matrixLocat ion)
997 { 996 {
998 WebTransformationMatrix quadRectMatrix; 997 WebTransformationMatrix quadRectMatrix;
999 quadRectTransform(&quadRectMatrix, drawTransform, quadRect); 998 quadRectTransform(&quadRectMatrix, drawTransform, quadRect);
1000 static float glMatrix[16]; 999 static float glMatrix[16];
1001 toGLMatrix(&glMatrix[0], frame.projectionMatrix * quadRectMatrix); 1000 toGLMatrix(&glMatrix[0], frame.projectionMatrix * quadRectMatrix);
1002 GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatr ix[0])); 1001 GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatr ix[0]));
1003 1002
1004 GLC(m_context, m_context->drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 )); 1003 GLC(m_context, m_context->drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ));
1005 } 1004 }
1006 1005
1007 void CCRendererGL::copyTextureToFramebuffer(const DrawingFrame& frame, int textu reId, const IntRect& rect, const WebTransformationMatrix& drawMatrix) 1006 void CCRendererGL::copyTextureToFramebuffer(const DrawingFrame& frame, int textu reId, const gfx::Rect& rect, const WebTransformationMatrix& drawMatrix)
1008 { 1007 {
1009 const RenderPassProgram* program = renderPassProgram(); 1008 const RenderPassProgram* program = renderPassProgram();
1010 1009
1011 GLC(context(), context()->activeTexture(GL_TEXTURE0)); 1010 GLC(context(), context()->activeTexture(GL_TEXTURE0));
1012 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, textureId)); 1011 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, textureId));
1013 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR)); 1012 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR));
1014 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR)); 1013 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR));
1015 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL _CLAMP_TO_EDGE)); 1014 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL _CLAMP_TO_EDGE));
1016 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL _CLAMP_TO_EDGE)); 1015 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL _CLAMP_TO_EDGE));
1017 1016
(...skipping 12 matching lines...) Expand all
1030 bool CCRendererGL::swapBuffers() 1029 bool CCRendererGL::swapBuffers()
1031 { 1030 {
1032 DCHECK(m_visible); 1031 DCHECK(m_visible);
1033 DCHECK(!m_isFramebufferDiscarded); 1032 DCHECK(!m_isFramebufferDiscarded);
1034 1033
1035 TRACE_EVENT0("cc", "CCRendererGL::swapBuffers"); 1034 TRACE_EVENT0("cc", "CCRendererGL::swapBuffers");
1036 // We're done! Time to swapbuffers! 1035 // We're done! Time to swapbuffers!
1037 1036
1038 if (m_capabilities.usingPartialSwap) { 1037 if (m_capabilities.usingPartialSwap) {
1039 // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport) 1038 // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
1040 m_swapBufferRect.intersect(IntRect(IntPoint(), viewportSize())); 1039 m_swapBufferRect = m_swapBufferRect.Intersect(gfx::Rect(gfx::Point(), vi ewportSize()));
1041 int flippedYPosOfRectBottom = viewportHeight() - m_swapBufferRect.y() - m_swapBufferRect.height(); 1040 int flippedYPosOfRectBottom = viewportHeight() - m_swapBufferRect.y() - m_swapBufferRect.height();
1042 m_context->postSubBufferCHROMIUM(m_swapBufferRect.x(), flippedYPosOfRect Bottom, m_swapBufferRect.width(), m_swapBufferRect.height()); 1041 m_context->postSubBufferCHROMIUM(m_swapBufferRect.x(), flippedYPosOfRect Bottom, m_swapBufferRect.width(), m_swapBufferRect.height());
1043 } else { 1042 } else {
1044 // Note that currently this has the same effect as swapBuffers; we shoul d 1043 // Note that currently this has the same effect as swapBuffers; we shoul d
1045 // consider exposing a different entry point on WebGraphicsContext3D. 1044 // consider exposing a different entry point on WebGraphicsContext3D.
1046 m_context->prepareTexture(); 1045 m_context->prepareTexture();
1047 } 1046 }
1048 1047
1049 m_swapBufferRect = IntRect(); 1048 m_swapBufferRect = gfx::Rect();
1050 1049
1051 return true; 1050 return true;
1052 } 1051 }
1053 1052
1054 void CCRendererGL::onSwapBuffersComplete() 1053 void CCRendererGL::onSwapBuffersComplete()
1055 { 1054 {
1056 m_client->onSwapBuffersComplete(); 1055 m_client->onSwapBuffersComplete();
1057 } 1056 }
1058 1057
1059 void CCRendererGL::onMemoryAllocationChanged(WebGraphicsMemoryAllocation allocat ion) 1058 void CCRendererGL::onMemoryAllocationChanged(WebGraphicsMemoryAllocation allocat ion)
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 GLC(m_context, m_context->deleteTexture(temporaryTexture)); 1189 GLC(m_context, m_context->deleteTexture(temporaryTexture));
1191 } 1190 }
1192 1191
1193 enforceMemoryPolicy(); 1192 enforceMemoryPolicy();
1194 } 1193 }
1195 1194
1196 bool CCRendererGL::getFramebufferTexture(CCScopedTexture* texture, const IntRect & deviceRect) 1195 bool CCRendererGL::getFramebufferTexture(CCScopedTexture* texture, const IntRect & deviceRect)
1197 { 1196 {
1198 DCHECK(!texture->id() || (texture->size() == deviceRect.size() && texture->f ormat() == GL_RGB)); 1197 DCHECK(!texture->id() || (texture->size() == deviceRect.size() && texture->f ormat() == GL_RGB));
1199 1198
1200 if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, deviceRect.si ze(), GL_RGB, CCResourceProvider::TextureUsageAny)) 1199 if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, cc::IntSize(d eviceRect.size()), GL_RGB, CCResourceProvider::TextureUsageAny))
1201 return false; 1200 return false;
1202 1201
1203 CCResourceProvider::ScopedWriteLockGL lock(m_resourceProvider, texture->id() ); 1202 CCResourceProvider::ScopedWriteLockGL lock(m_resourceProvider, texture->id() );
1204 GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, lock.textureId())); 1203 GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, lock.textureId()));
1205 GLC(m_context, m_context->copyTexImage2D(GL_TEXTURE_2D, 0, texture->format() , 1204 GLC(m_context, m_context->copyTexImage2D(GL_TEXTURE_2D, 0, texture->format() ,
1206 deviceRect.x(), deviceRect.y(), dev iceRect.width(), deviceRect.height(), 0)); 1205 deviceRect.x(), deviceRect.y(), dev iceRect.width(), deviceRect.height(), 0));
1207 return true; 1206 return true;
1208 } 1207 }
1209 1208
1210 bool CCRendererGL::useScopedTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& viewportRect) 1209 bool CCRendererGL::useScopedTexture(DrawingFrame& frame, const CCScopedTexture* texture, const gfx::Rect& viewportRect)
1211 { 1210 {
1212 DCHECK(texture->id()); 1211 DCHECK(texture->id());
1213 frame.currentRenderPass = 0; 1212 frame.currentRenderPass = 0;
1214 frame.currentTexture = texture; 1213 frame.currentTexture = texture;
1215 1214
1216 return bindFramebufferToTexture(frame, texture, viewportRect); 1215 return bindFramebufferToTexture(frame, texture, viewportRect);
1217 } 1216 }
1218 1217
1219 void CCRendererGL::bindFramebufferToOutputSurface(DrawingFrame& frame) 1218 void CCRendererGL::bindFramebufferToOutputSurface(DrawingFrame& frame)
1220 { 1219 {
1221 m_currentFramebufferLock.reset(); 1220 m_currentFramebufferLock.reset();
1222 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0)); 1221 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0));
1223 } 1222 }
1224 1223
1225 bool CCRendererGL::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedT exture* texture, const IntRect& framebufferRect) 1224 bool CCRendererGL::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedT exture* texture, const gfx::Rect& framebufferRect)
1226 { 1225 {
1227 DCHECK(texture->id()); 1226 DCHECK(texture->id());
1228 1227
1229 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, m_offscreenFramebu fferId)); 1228 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, m_offscreenFramebu fferId));
1230 m_currentFramebufferLock = make_scoped_ptr(new CCResourceProvider::ScopedWri teLockGL(m_resourceProvider, texture->id())); 1229 m_currentFramebufferLock = make_scoped_ptr(new CCResourceProvider::ScopedWri teLockGL(m_resourceProvider, texture->id()));
1231 unsigned textureId = m_currentFramebufferLock->textureId(); 1230 unsigned textureId = m_currentFramebufferLock->textureId();
1232 GLC(m_context, m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTA CHMENT0, GL_TEXTURE_2D, textureId, 0)); 1231 GLC(m_context, m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTA CHMENT0, GL_TEXTURE_2D, textureId, 0));
1233 1232
1234 DCHECK(m_context->checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_C OMPLETE); 1233 DCHECK(m_context->checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_C OMPLETE);
1235 1234
1236 initializeMatrices(frame, framebufferRect, false); 1235 initializeMatrices(frame, framebufferRect, false);
1237 setDrawViewportSize(framebufferRect.size()); 1236 setDrawViewportSize(framebufferRect.size());
1238 1237
1239 return true; 1238 return true;
1240 } 1239 }
1241 1240
1242 void CCRendererGL::enableScissorTestRect(const IntRect& scissorRect) 1241 void CCRendererGL::enableScissorTestRect(const gfx::Rect& scissorRect)
1243 { 1242 {
1244 GLC(m_context, m_context->enable(GL_SCISSOR_TEST)); 1243 GLC(m_context, m_context->enable(GL_SCISSOR_TEST));
1245 GLC(m_context, m_context->scissor(scissorRect.x(), scissorRect.y(), scissorR ect.width(), scissorRect.height())); 1244 GLC(m_context, m_context->scissor(scissorRect.x(), scissorRect.y(), scissorR ect.width(), scissorRect.height()));
1246 } 1245 }
1247 1246
1248 void CCRendererGL::disableScissorTest() 1247 void CCRendererGL::disableScissorTest()
1249 { 1248 {
1250 GLC(m_context, m_context->disable(GL_SCISSOR_TEST)); 1249 GLC(m_context, m_context->disable(GL_SCISSOR_TEST));
1251 } 1250 }
1252 1251
1253 void CCRendererGL::setDrawViewportSize(const IntSize& viewportSize) 1252 void CCRendererGL::setDrawViewportSize(const gfx::Size& viewportSize)
1254 { 1253 {
1255 GLC(m_context, m_context->viewport(0, 0, viewportSize.width(), viewportSize. height())); 1254 GLC(m_context, m_context->viewport(0, 0, viewportSize.width(), viewportSize. height()));
1256 } 1255 }
1257 1256
1258 bool CCRendererGL::makeContextCurrent() 1257 bool CCRendererGL::makeContextCurrent()
1259 { 1258 {
1260 return m_context->makeContextCurrent(); 1259 return m_context->makeContextCurrent();
1261 } 1260 }
1262 1261
1263 bool CCRendererGL::initializeSharedObjects() 1262 bool CCRendererGL::initializeSharedObjects()
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 1513
1515 releaseRenderPassTextures(); 1514 releaseRenderPassTextures();
1516 } 1515 }
1517 1516
1518 bool CCRendererGL::isContextLost() 1517 bool CCRendererGL::isContextLost()
1519 { 1518 {
1520 return (m_context->getGraphicsResetStatusARB() != GL_NO_ERROR); 1519 return (m_context->getGraphicsResetStatusARB() != GL_NO_ERROR);
1521 } 1520 }
1522 1521
1523 } // namespace cc 1522 } // namespace cc
OLDNEW
« no previous file with comments | « cc/gl_renderer.h ('k') | cc/io_surface_draw_quad.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698