bool GLScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib, const GLMatrix &transform, const CompRegion ®ion, CompOutput *output, unsigned int mask) { WRAPABLE_HND_FUNCTN_RETURN (bool, glPaintOutput, sAttrib, transform, region, output, mask) GLMatrix sTransform = transform; if (mask & PAINT_SCREEN_REGION_MASK) { if (mask & PAINT_SCREEN_TRANSFORMED_MASK) { if (mask & PAINT_SCREEN_FULL_MASK) { glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output), output, mask); return true; } return false; } setLighting (false); sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); /* * Sometimes region might be empty but we still need to force the * repaint. This can happen when a fullscreen window is unredirected, * and damageScreen is called. CompositeScreen::handlePaintTimeout * then subtracts the whole screen of damage because it's an overlay * and we're left with an empty damage region. * Even when this happens we may want to force the repaint if * windows are getting transformed (and so the unredirected window * needs to be redirected again). */ if (!region.isEmpty () || (mask & PAINT_SCREEN_FULL_MASK) || (mask & PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)) priv->paintOutputRegion (sTransform, region, output, mask); return true; } else if (mask & PAINT_SCREEN_FULL_MASK) { glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output), output, mask); return true; } else { return false; } }
void GridAnim::addGeometry (const GLTexture::MatrixList &matrix, const CompRegion ®ion, const CompRegion &clip, unsigned int maxGridWidth, unsigned int maxGridHeight) { if (region.isEmpty ()) // nothing to do return; GLfloat *v, *vMax; bool notUsing3dCoords = !using3D (); CompRect outRect (mAWindow->savedRectsValid () ? mAWindow->savedOutRect () : mWindow->outputRect ()); CompWindowExtents outExtents (mAWindow->savedRectsValid () ? mAWindow->savedOutExtents () : mWindow->output ()); // window output (contents + decorations + shadows) coordinates and size int ox = outRect.x (); int oy = outRect.y (); int owidth = outRect.width (); int oheight = outRect.height (); // to be used if event is shade/unshade float winContentsY = oy + outExtents.top; float winContentsHeight = oheight - outExtents.top - outExtents.bottom; GLWindow *gWindow = GLWindow::get (mWindow); GLVertexBuffer *vertexBuffer = gWindow->vertexBuffer (); int vSize = vertexBuffer->getVertexStride (); // Indentation kept to provide a clean diff with the old code, for now... { int y1 = outRect.y1 (); int x2 = outRect.x2 (); int y2 = outRect.y2 (); float gridW = (float)owidth / (mGridWidth - 1); float gridH; if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part gridH = mDecorTopHeight; else if (y2 > winContentsY + winContentsHeight) // if at bottom gridH = mDecorBottomHeight; else // in window contents (only in Y coords) { float winContentsHeight = oheight - (mDecorTopHeight + mDecorBottomHeight); gridH = winContentsHeight / (mGridHeight - 3); } } else gridH = (float)oheight / (mGridHeight - 1); int oldCount = vertexBuffer->countVertices (); gWindow->glAddGeometry (matrix, region, clip, gridW, gridH); int newCount = vertexBuffer->countVertices (); v = vertexBuffer->getVertices () + (oldCount * vSize); vMax = vertexBuffer->getVertices () + (newCount * vSize); float x, y, topiyFloat; // For each vertex for (; v < vMax; v += vSize) { x = v[0]; y = v[1]; if (y > y2) y = y2; if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part { topiyFloat = (y - oy) / mDecorTopHeight; topiyFloat = MIN (topiyFloat, 0.999); // avoid 1.0 } else if (y2 > winContentsY + winContentsHeight) // if at bottom topiyFloat = (mGridHeight - 2) + (mDecorBottomHeight ? (y - winContentsY - winContentsHeight) / mDecorBottomHeight : 0); else // in window contents (only in Y coords) topiyFloat = (mGridHeight - 3) * (y - winContentsY) / winContentsHeight + 1; } else topiyFloat = (mGridHeight - 1) * (y - oy) / oheight; // topiy should be at most (mGridHeight - 2) int topiy = (int)(topiyFloat + 1e-4); if (topiy == mGridHeight - 1) --topiy; int bottomiy = topiy + 1; float iny = topiyFloat - topiy; float inyRest = 1 - iny; // End of calculations for y // Indentation kept to provide a clean diff with the old code... { if (x > x2) x = x2; // find containing grid cell (leftix rightix) x (topiy bottomiy) float leftixFloat = (mGridWidth - 1) * (x - ox) / owidth; int leftix = (int)(leftixFloat + 1e-4); if (leftix == mGridWidth - 1) --leftix; int rightix = leftix + 1; // GridModel::GridObjects that are at top, bottom, left, right corners of quad GridModel::GridObject *objToTopLeft = &(mModel->mObjects[topiy * mGridWidth + leftix]); GridModel::GridObject *objToTopRight = &(mModel->mObjects[topiy * mGridWidth + rightix]); GridModel::GridObject *objToBottomLeft = &(mModel->mObjects[bottomiy * mGridWidth + leftix]); GridModel::GridObject *objToBottomRight = &(mModel->mObjects[bottomiy * mGridWidth + rightix]); Point3d &objToTopLeftPos = objToTopLeft->mPosition; Point3d &objToTopRightPos = objToTopRight->mPosition; Point3d &objToBottomLeftPos = objToBottomLeft->mPosition; Point3d &objToBottomRightPos = objToBottomRight->mPosition; // find position in cell by taking remainder of flooring float inx = leftixFloat - leftix; float inxRest = 1 - inx; // Interpolate to find deformed coordinates float hor1x = (inxRest * objToTopLeftPos.x () + inx * objToTopRightPos.x ()); float hor1y = (inxRest * objToTopLeftPos.y () + inx * objToTopRightPos.y ()); float hor1z = (notUsing3dCoords ? 0 : inxRest * objToTopLeftPos.z () + inx * objToTopRightPos.z ()); float hor2x = (inxRest * objToBottomLeftPos.x () + inx * objToBottomRightPos.x ()); float hor2y = (inxRest * objToBottomLeftPos.y () + inx * objToBottomRightPos.y ()); float hor2z = (notUsing3dCoords ? 0 : inxRest * objToBottomLeftPos.z () + inx * objToBottomRightPos.z ()); float deformedX = inyRest * hor1x + iny * hor2x; float deformedY = inyRest * hor1y + iny * hor2y; float deformedZ = inyRest * hor1z + iny * hor2z; v[0] = deformedX; v[1] = deformedY; v[2] = deformedZ; } } } }
void GridAnim::addGeometry (const GLTexture::MatrixList &matrix, const CompRegion ®ion, const CompRegion &clip, unsigned int maxGridWidth, unsigned int maxGridHeight) { unsigned int nMatrix = matrix.size (); int nVertices, nIndices; GLushort *i; GLfloat *v; int x1, y1, x2, y2; float winContentsY, winContentsHeight; float deformedX, deformedY; float deformedZ = 0; int nVertX, nVertY; int vSize; float gridW, gridH; bool rect = true; bool notUsing3dCoords = !using3D (); if (region.isEmpty ()) // nothing to do return; GLWindow::Geometry &geometry = GLWindow::get (mWindow)->geometry (); for (unsigned int it = 0; it < nMatrix; it++) { if (matrix[it].xy != 0.0f || matrix[it].yx != 0.0f) { rect = false; break; } } CompRect outRect (mAWindow->savedRectsValid () ? mAWindow->savedOutRect () : mWindow->outputRect ()); CompWindowExtents outExtents (mAWindow->savedRectsValid () ? mAWindow->savedOutExtents () : mWindow->output ()); // window output (contents + decorations + shadows) coordinates and size int ox = outRect.x (); int oy = outRect.y (); int owidth = outRect.width (); int oheight = outRect.height (); // to be used if event is shade/unshade winContentsY = oy + outExtents.top; winContentsHeight = oheight - outExtents.top - outExtents.bottom; geometry.texUnits = (int)nMatrix; if (geometry.vCount == 0) { // reset geometry.indexCount = 0; geometry.texCoordSize = 4; } geometry.vertexStride = 3 + geometry.texUnits * geometry.texCoordSize; vSize = geometry.vertexStride; nVertices = geometry.vCount; nIndices = geometry.indexCount; v = geometry.vertices + (nVertices * vSize); i = geometry.indices + nIndices; // For each clip passed to this function foreach (const CompRect &pClip, region.rects ()) { x1 = pClip.x1 (); y1 = pClip.y1 (); x2 = pClip.x2 (); y2 = pClip.y2 (); gridW = (float)owidth / (mGridWidth - 1); if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part { gridH = mDecorTopHeight; } else if (y2 > winContentsY + winContentsHeight) // if at bottom { gridH = mDecorBottomHeight; } else // in window contents (only in Y coords) { float winContentsHeight = oheight - (mDecorTopHeight + mDecorBottomHeight); gridH = winContentsHeight / (mGridHeight - 3); } } else gridH = (float)oheight / (mGridHeight - 1); // nVertX, nVertY: number of vertices for this clip in x and y dimensions // + 2 to avoid running short of vertices in some cases nVertX = ceil ((x2 - x1) / gridW) + 2; nVertY = (gridH ? ceil ((y2 - y1) / gridH) : 0) + 2; // Allocate 4 indices for each quad int newIndexSize = nIndices + ((nVertX - 1) * (nVertY - 1) * 4); if (newIndexSize > geometry.indexSize) { if (!geometry.moreIndices (newIndexSize)) return; i = geometry.indices + nIndices; } // Assign quad vertices to indices for (int jy = 0; jy < nVertY - 1; jy++) { for (int jx = 0; jx < nVertX - 1; jx++) { *i++ = nVertices + nVertX * (2 * jy + 1) + jx; *i++ = nVertices + nVertX * (2 * jy + 1) + jx + 1; *i++ = nVertices + nVertX * 2 * jy + jx + 1; *i++ = nVertices + nVertX * 2 * jy + jx; nIndices += 4; } } // Allocate vertices int newVertexSize = (nVertices + nVertX * (2 * nVertY - 2)) * vSize; if (newVertexSize > geometry.vertexSize) { if (!geometry.moreVertices (newVertexSize)) return; v = geometry.vertices + (nVertices * vSize); } float rowTexCoordQ = 1; float prevRowCellWidth = 0; // this initial value won't be used float rowCellWidth = 0; int clipRowSize = nVertX * vSize; // For each vertex float y = y1; for (int jy = 0; jy < nVertY; jy++) { float topiyFloat; bool applyOffsets = true; if (y > y2) y = y2; // Do calculations for y here to avoid repeating // them unnecessarily in the x loop if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part { topiyFloat = (y - oy) / mDecorTopHeight; topiyFloat = MIN (topiyFloat, 0.999); // avoid 1.0 applyOffsets = false; } else if (y2 > winContentsY + winContentsHeight) // if at bottom { topiyFloat = (mGridHeight - 2) + (mDecorBottomHeight ? (y - winContentsY - winContentsHeight) / mDecorBottomHeight : 0); applyOffsets = false; } else // in window contents (only in Y coords) { topiyFloat = (mGridHeight - 3) * (y - winContentsY) / winContentsHeight + 1; } } else { topiyFloat = (mGridHeight - 1) * (y - oy) / oheight; } // topiy should be at most (mGridHeight - 2) int topiy = (int)(topiyFloat + 1e-4); if (topiy == mGridHeight - 1) topiy--; int bottomiy = topiy + 1; float iny = topiyFloat - topiy; float inyRest = 1 - iny; // End of calculations for y float x = x1; for (int jx = 0; jx < nVertX; jx++) { if (x > x2) x = x2; // find containing grid cell (leftix rightix) x (topiy bottomiy) float leftixFloat = (mGridWidth - 1) * (x - ox) / owidth; int leftix = (int)(leftixFloat + 1e-4); if (leftix == mGridWidth - 1) leftix--; int rightix = leftix + 1; // GridModel::GridObjects that are at top, bottom, left, right corners of quad GridModel::GridObject *objToTopLeft = &(mModel->mObjects[topiy * mGridWidth + leftix]); GridModel::GridObject *objToTopRight = &(mModel->mObjects[topiy * mGridWidth + rightix]); GridModel::GridObject *objToBottomLeft = &(mModel->mObjects[bottomiy * mGridWidth + leftix]); GridModel::GridObject *objToBottomRight = &(mModel->mObjects[bottomiy * mGridWidth + rightix]); Point3d &objToTopLeftPos = objToTopLeft->mPosition; Point3d &objToTopRightPos = objToTopRight->mPosition; Point3d &objToBottomLeftPos = objToBottomLeft->mPosition; Point3d &objToBottomRightPos = objToBottomRight->mPosition; // find position in cell by taking remainder of flooring float inx = leftixFloat - leftix; float inxRest = 1 - inx; // Interpolate to find deformed coordinates float hor1x = (inxRest * objToTopLeftPos.x () + inx * objToTopRightPos.x ()); float hor1y = (inxRest * objToTopLeftPos.y () + inx * objToTopRightPos.y ()); float hor1z = (notUsing3dCoords ? 0 : inxRest * objToTopLeftPos.z () + inx * objToTopRightPos.z ()); float hor2x = (inxRest * objToBottomLeftPos.x () + inx * objToBottomRightPos.x ()); float hor2y = (inxRest * objToBottomLeftPos.y () + inx * objToBottomRightPos.y ()); float hor2z = (notUsing3dCoords ? 0 : inxRest * objToBottomLeftPos.z () + inx * objToBottomRightPos.z ()); deformedX = inyRest * hor1x + iny * hor2x; deformedY = inyRest * hor1y + iny * hor2y; deformedZ = inyRest * hor1z + iny * hor2z; // Texture coordinates (s, t, r, q) if (mUseQTexCoord) { if (jx == 1) rowCellWidth = deformedX - v[-3]; // do only once per row for all rows except row 0 if (jy > 0 && jx == 1) { rowTexCoordQ = (rowCellWidth / prevRowCellWidth); for (unsigned int it = 0; it < nMatrix; it++, v += 4) { // update first column // (since we didn't know rowTexCoordQ before) v[-vSize] *= rowTexCoordQ; // multiply s & t by q v[-vSize + 1] *= rowTexCoordQ; v[-vSize + 3] = rowTexCoordQ; // copy q } v -= nMatrix * 4; } } // Loop for each texture element // (4 texture coordinates for each one) for (unsigned int it = 0; it < nMatrix; it++, v += 4) { float offsetY = 0; if (rect) { if (applyOffsets && y < y2) offsetY = objToTopLeft->mOffsetTexCoordForQuadAfter.y (); v[0] = COMP_TEX_COORD_X (matrix[it], x); // s v[1] = COMP_TEX_COORD_Y (matrix[it], y + offsetY); // t } else { if (applyOffsets && y < y2) // FIXME: // The correct y offset below produces wrong // texture coordinates for some reason. offsetY = 0; // offsetY = objToTopLeft->offsetTexCoordForQuadAfter.y; v[0] = COMP_TEX_COORD_XY (matrix[it], x, y + offsetY); // s v[1] = COMP_TEX_COORD_YX (matrix[it], x, y + offsetY); // t } v[2] = 0; // r if (0 < jy && jy < nVertY - 1) { // copy s, t, r to duplicate row memcpy (v + clipRowSize, v, 3 * sizeof (GLfloat)); v[3 + clipRowSize] = 1; // q } if (applyOffsets && objToTopLeft->mOffsetTexCoordForQuadBefore.y () != 0) { // After copying to next row, update texture y coord // by following object's offset offsetY = objToTopLeft->mOffsetTexCoordForQuadBefore.y (); if (rect) { v[1] = COMP_TEX_COORD_Y (matrix[it], y + offsetY); } else { v[0] = COMP_TEX_COORD_XY (matrix[it], x, y + offsetY); v[1] = COMP_TEX_COORD_YX (matrix[it], x, y + offsetY); } } if (mUseQTexCoord) { v[3] = rowTexCoordQ; // q if (jx > 0) // since column 0 is updated when jx == 1 { // multiply s & t by q v[0] *= rowTexCoordQ; v[1] *= rowTexCoordQ; } } else { v[3] = 1; // q } } v[0] = deformedX; v[1] = deformedY; v[2] = deformedZ; // Copy vertex coordinates to duplicate row if (0 < jy && jy < nVertY - 1) memcpy (v + clipRowSize, v, 3 * sizeof (GLfloat)); nVertices++; // increment x properly (so that coordinates fall on grid intersections) x = rightix * gridW + ox; v += 3; // move on to next vertex } if (mUseQTexCoord) prevRowCellWidth = rowCellWidth; if (0 < jy && jy < nVertY - 1) { v += clipRowSize; // skip the duplicate row nVertices += nVertX; } // increment y properly (so that coordinates fall on grid intersections) if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { y += gridH; } else { y = bottomiy * gridH + oy; } } } geometry.vCount = nVertices; geometry.indexCount = nIndices; }