void GrInOrderDrawBuffer::drawRect(const GrRect& rect, const GrMatrix* matrix, StageBitfield stageEnableBitfield, const GrRect* srcRects[], const GrMatrix* srcMatrices[]) { GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad)); GrAssert(!(fDraws.empty() && fCurrQuad)); GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer)); // if we have a quad IB then either append to the previous run of // rects or start a new run if (fMaxQuads) { bool appendToPreviousDraw = false; GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects); AutoReleaseGeometry geo(this, layout, 4, 0); AutoViewMatrixRestore avmr(this); GrMatrix combinedMatrix = this->getViewMatrix(); this->setViewMatrix(GrMatrix::I()); if (NULL != matrix) { combinedMatrix.preConcat(*matrix); } SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices()); // we don't want to miss an opportunity to batch rects together // simply because the clip has changed if the clip doesn't affect // the rect. bool disabledClip = false; if (this->isClipState() && fClip.isRect()) { GrRect clipRect = fClip.getRect(0); // If the clip rect touches the edge of the viewport, extended it // out (close) to infinity to avoid bogus intersections. // We might consider a more exact clip to viewport if this // conservative test fails. const GrRenderTarget* target = this->getRenderTarget(); if (0 >= clipRect.fLeft) { clipRect.fLeft = GR_ScalarMin; } if (target->width() <= clipRect.fRight) { clipRect.fRight = GR_ScalarMax; } if (0 >= clipRect.top()) { clipRect.fTop = GR_ScalarMin; } if (target->height() <= clipRect.fBottom) { clipRect.fBottom = GR_ScalarMax; } int stride = VertexSize(layout); bool insideClip = true; for (int v = 0; v < 4; ++v) { const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride); if (!clipRect.contains(p)) { insideClip = false; break; } } if (insideClip) { this->disableState(kClip_StateBit); disabledClip = true; } } if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 && fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) { int vsize = VertexSize(layout); Draw& lastDraw = fDraws.back(); GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer); GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType); GrAssert(0 == lastDraw.fVertexCount % 4); GrAssert(0 == lastDraw.fIndexCount % 6); GrAssert(0 == lastDraw.fStartIndex); GeometryPoolState& poolState = fGeoPoolStateStack.back(); bool clearSinceLastDraw = fClears.count() && fClears.back().fBeforeDrawIdx == fDraws.count(); appendToPreviousDraw = !clearSinceLastDraw && lastDraw.fVertexBuffer == poolState.fPoolVertexBuffer && (fCurrQuad * 4 + lastDraw.fStartVertex) == poolState.fPoolStartVertex; if (appendToPreviousDraw) { lastDraw.fVertexCount += 4; lastDraw.fIndexCount += 6; fCurrQuad += 1; // we reserved above, so we should be the first // use of this vertex reserveation. GrAssert(0 == poolState.fUsedPoolVertexBytes); poolState.fUsedPoolVertexBytes = 4 * vsize; } } if (!appendToPreviousDraw) { this->setIndexSourceToBuffer(fQuadIndexBuffer); drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6); fCurrQuad = 1; fLastRectVertexLayout = layout; } if (disabledClip) { this->enableState(kClip_StateBit); } } else { INHERITED::drawRect(rect, matrix, stageEnableBitfield, srcRects, srcMatrices); } }
void GrGpuGL::flushViewMatrix(DrawType type) { const GrGLRenderTarget* rt = static_cast<const GrGLRenderTarget*>(this->getDrawState().getRenderTarget()); SkISize viewportSize; const GrGLIRect& viewport = rt->getViewport(); viewportSize.set(viewport.fWidth, viewport.fHeight); const GrMatrix& vm = this->getDrawState().getViewMatrix(); if (kStencilPath_DrawType == type) { if (fHWPathMatrixState.fViewMatrix != vm || fHWPathMatrixState.fRTSize != viewportSize) { // rescale the coords from skia's "device" coords to GL's normalized coords, // and perform a y-flip. GrMatrix m; m.setScale(GrIntToScalar(2) / rt->width(), GrIntToScalar(-2) / rt->height()); m.postTranslate(-GR_Scalar1, GR_Scalar1); m.preConcat(vm); // GL wants a column-major 4x4. GrGLfloat mv[] = { // col 0 GrScalarToFloat(m[GrMatrix::kMScaleX]), GrScalarToFloat(m[GrMatrix::kMSkewY]), 0, GrScalarToFloat(m[GrMatrix::kMPersp0]), // col 1 GrScalarToFloat(m[GrMatrix::kMSkewX]), GrScalarToFloat(m[GrMatrix::kMScaleY]), 0, GrScalarToFloat(m[GrMatrix::kMPersp1]), // col 2 0, 0, 0, 0, // col3 GrScalarToFloat(m[GrMatrix::kMTransX]), GrScalarToFloat(m[GrMatrix::kMTransY]), 0.0f, GrScalarToFloat(m[GrMatrix::kMPersp2]) }; GL_CALL(MatrixMode(GR_GL_PROJECTION)); GL_CALL(LoadMatrixf(mv)); fHWPathMatrixState.fViewMatrix = vm; fHWPathMatrixState.fRTSize = viewportSize; } } else if (!fCurrentProgram->fViewMatrix.cheapEqualTo(vm) || fCurrentProgram->fViewportSize != viewportSize) { GrMatrix m; m.setAll( GrIntToScalar(2) / viewportSize.fWidth, 0, -GR_Scalar1, 0,-GrIntToScalar(2) / viewportSize.fHeight, GR_Scalar1, 0, 0, GrMatrix::I()[8]); m.setConcat(m, vm); // ES doesn't allow you to pass true to the transpose param, // so do our own transpose GrGLfloat mt[] = { GrScalarToFloat(m[GrMatrix::kMScaleX]), GrScalarToFloat(m[GrMatrix::kMSkewY]), GrScalarToFloat(m[GrMatrix::kMPersp0]), GrScalarToFloat(m[GrMatrix::kMSkewX]), GrScalarToFloat(m[GrMatrix::kMScaleY]), GrScalarToFloat(m[GrMatrix::kMPersp1]), GrScalarToFloat(m[GrMatrix::kMTransX]), GrScalarToFloat(m[GrMatrix::kMTransY]), GrScalarToFloat(m[GrMatrix::kMPersp2]) }; fCurrentProgram->fUniformManager.setMatrix3f(fCurrentProgram->fUniforms.fViewMatrixUni, mt); fCurrentProgram->fViewMatrix = vm; fCurrentProgram->fViewportSize = viewportSize; } }