summaryrefslogtreecommitdiff
path: root/src/paint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/paint.c')
-rw-r--r--src/paint.c399
1 files changed, 229 insertions, 170 deletions
diff --git a/src/paint.c b/src/paint.c
index 5174e95..29e5646 100644
--- a/src/paint.c
+++ b/src/paint.c
@@ -86,8 +86,14 @@ paintTransformedScreen (CompScreen *screen,
glEnable (GL_STENCIL_TEST);
for (w = screen->windows; w; w = w->next)
- (*screen->paintWindow) (w, wAttrib, &screen->region,
- windowMask);
+ {
+ if (w->destroyed || w->attrib.map_state != IsViewable)
+ continue;
+
+ if (w->damaged)
+ (*screen->paintWindow) (w, wAttrib, &screen->region,
+ windowMask);
+ }
glDisable (GL_STENCIL_TEST);
@@ -102,7 +108,13 @@ paintTransformedScreen (CompScreen *screen,
(*screen->paintBackground) (screen, &screen->region, backgroundMask);
for (w = screen->windows; w; w = w->next)
- (*screen->paintWindow) (w, wAttrib, &screen->region, windowMask);
+ {
+ if (w->destroyed || w->attrib.map_state != IsViewable)
+ continue;
+
+ if (w->damaged)
+ (*screen->paintWindow) (w, wAttrib, &screen->region, windowMask);
+ }
glPopMatrix ();
}
@@ -164,7 +176,7 @@ paintScreen (CompScreen *screen,
/* paint solid windows */
for (w = screen->reverseWindows; w; w = w->prev)
{
- if (w->invisible)
+ if (w->destroyed || w->invisible)
continue;
if ((*screen->paintWindow) (w, wAttrib, tmpRegion,
@@ -173,18 +185,23 @@ paintScreen (CompScreen *screen,
/* copy region */
XSubtractRegion (tmpRegion, &emptyRegion, w->clip);
+
+ if (!tmpRegion->numRects)
+ break;
}
- (*screen->paintBackground) (screen, tmpRegion, 0);
+ if (tmpRegion->numRects)
+ (*screen->paintBackground) (screen, tmpRegion, 0);
/* paint translucent windows */
for (w = screen->windows; w; w = w->next)
{
- if (w->invisible)
+ if (w->destroyed || w->invisible)
continue;
- (*screen->paintWindow) (w, wAttrib, w->clip,
- PAINT_WINDOW_TRANSLUCENT_MASK);
+ if (w->clip->numRects)
+ (*screen->paintWindow) (w, wAttrib, w->clip,
+ PAINT_WINDOW_TRANSLUCENT_MASK);
}
glPopMatrix ();
@@ -192,146 +209,127 @@ paintScreen (CompScreen *screen,
return TRUE;
}
-#define ADD_QUAD(data, w, x1, y1, x2, y2) \
- if (!(w)->pixmap) \
- bindWindow (w); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x1); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y2); \
- *(data)++ = (x1); \
- *(data)++ = (y2); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x2); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y2); \
- *(data)++ = (x2); \
- *(data)++ = (y2); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x2); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y1); \
- *(data)++ = (x2); \
- *(data)++ = (y1); \
- *(data)++ = X_WINDOW_TO_TEXTURE_SPACE (w, x1); \
- *(data)++ = Y_WINDOW_TO_TEXTURE_SPACE (w, y1); \
- *(data)++ = (x1); \
+#define ADD_QUAD(data, m, n, x1, y1, x2, y2) \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x1, y2); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x1, y2); \
+ } \
+ *(data)++ = (x1); \
+ *(data)++ = (y2); \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x2, y2); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x2, y2); \
+ } \
+ *(data)++ = (x2); \
+ *(data)++ = (y2); \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x2, y1); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x2, y1); \
+ } \
+ *(data)++ = (x2); \
+ *(data)++ = (y1); \
+ for (it = 0; it < n; it++) \
+ { \
+ *(data)++ = COMP_TEX_COORD_X (&m[it], x1, y1); \
+ *(data)++ = COMP_TEX_COORD_Y (&m[it], x1, y1); \
+ } \
+ *(data)++ = (x1); \
*(data)++ = (y1)
-#define ADD_BOX(data, w, box) \
- ADD_QUAD (data, w, (box)->x1, (box)->y1, (box)->x2, (box)->y2)
-
Bool
-paintWindow (CompWindow *w,
- const WindowPaintAttrib *attrib,
- Region region,
- unsigned int mask)
+moreWindowVertices (CompWindow *w,
+ int newSize)
{
- BoxPtr pClip;
- int nClip, n;
- GLfloat *data, *d;
- GLushort opacity;
- int x1, y1, x2, y2;
-
- if (!region->numRects)
- return TRUE;
-
- if (w->destroyed || w->attrib.map_state != IsViewable)
- return TRUE;
-
- if (mask & PAINT_WINDOW_SOLID_MASK)
+ if (newSize > w->vertexSize)
{
- if (w->alpha)
- return FALSE;
+ GLfloat *vertices;
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (opacity != OPAQUE)
+ vertices = realloc (w->vertices, sizeof (GLfloat) * newSize);
+ if (!vertices)
return FALSE;
+
+ w->vertices = vertices;
+ w->vertexSize = newSize;
}
- else if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
+
+ return TRUE;
+}
+
+Bool
+moreWindowIndices (CompWindow *w,
+ int newSize)
+{
+ if (newSize > w->indexSize)
{
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (!w->alpha && opacity == OPAQUE)
+ GLushort *indices;
+
+ indices = realloc (w->indices, sizeof (GLushort) * newSize);
+ if (!indices)
return FALSE;
- }
- else
- {
- opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
- if (w->alpha || opacity != OPAQUE)
- mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
- else
- mask |= PAINT_WINDOW_SOLID_MASK;
+
+ w->indices = indices;
+ w->indexSize = newSize;
}
- if (attrib->xTranslate != 0.0f ||
- attrib->yTranslate != 0.0f ||
- attrib->xScale != 1.0f ||
- attrib->yScale != 1.0f)
- {
- nClip = w->region->numRects;
- pClip = w->region->rects;
+ return TRUE;
+}
- mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
+void
+addWindowGeometry (CompWindow *w,
+ CompMatrix *matrix,
+ int nMatrix,
+ Region region,
+ Region clip)
+{
+ BoxRec full;
- data = malloc (sizeof (GLfloat) * nClip * 16);
- if (!data)
- return FALSE;
+ w->texUnits = nMatrix;
- d = data;
+ full = clip->extents;
+ if (region->extents.x1 > full.x1)
+ full.x1 = region->extents.x1;
+ if (region->extents.y1 > full.y1)
+ full.y1 = region->extents.y1;
+ if (region->extents.x2 < full.x2)
+ full.x2 = region->extents.x2;
+ if (region->extents.y2 < full.y2)
+ full.y2 = region->extents.y2;
- n = nClip;
- while (nClip--)
- {
- x1 = pClip->x1 - w->attrib.x;
- y1 = pClip->y1 - w->attrib.y;
- x2 = pClip->x2 - w->attrib.x;
- y2 = pClip->y2 - w->attrib.y;
+ if (full.x1 < full.x2 && full.y1 < full.y2)
+ {
+ BoxPtr pBox;
+ int nBox;
+ BoxPtr pClip;
+ int nClip;
+ BoxRec cbox;
+ int vSize;
+ int n, it, x1, y1, x2, y2;
+ GLfloat *d;
- ADD_QUAD (d, w, x1, y1, x2, y2);
+ pBox = region->rects;
+ nBox = region->numRects;
- pClip++;
+ vSize = 2 + nMatrix * 2;
+
+ n = w->vCount / 4;
+
+ if ((n + nBox) * vSize * 4 > w->vertexSize)
+ {
+ if (!moreWindowVertices (w, (n + nBox) * vSize * 4))
+ return;
}
- }
- else
- {
- BoxRec clip, full;
- BoxPtr pExtent = &region->extents;
- BoxPtr pBox = region->rects;
- int nBox = region->numRects;
- int dataSize;
-
- full.x1 = 0;
- full.y1 = 0;
- full.x2 = w->width;
- full.y2 = w->height;
-
- x1 = pExtent->x1 - w->attrib.x;
- y1 = pExtent->y1 - w->attrib.y;
- x2 = pExtent->x2 - w->attrib.x;
- y2 = pExtent->y2 - w->attrib.y;
-
- if (x1 > 0)
- full.x1 = x1;
- if (y1 > 0)
- full.y1 = y1;
- if (x2 < w->width)
- full.x2 = x2;
- if (y2 < w->height)
- full.y2 = y2;
-
- if (full.x1 >= full.x2 || full.y1 >= full.y2)
- return TRUE;
-
- dataSize = nBox * 16;
- data = malloc (sizeof (GLfloat) * dataSize);
- if (!data)
- return FALSE;
- d = data;
- n = 0;
+ d = w->vertices + (w->vCount * vSize);
- pBox = region->rects;
- nBox = region->numRects;
while (nBox--)
{
- x1 = pBox->x1 - w->attrib.x;
- y1 = pBox->y1 - w->attrib.y;
- x2 = pBox->x2 - w->attrib.x;
- y2 = pBox->y2 - w->attrib.y;
+ x1 = pBox->x1;
+ y1 = pBox->y1;
+ x2 = pBox->x2;
+ y2 = pBox->y2;
pBox++;
@@ -346,50 +344,45 @@ paintWindow (CompWindow *w,
if (x1 < x2 && y1 < y2)
{
- nClip = w->region->numRects;
+ nClip = clip->numRects;
if (nClip == 1)
{
- ADD_QUAD (d, w, x1, y1, x2, y2);
+ ADD_QUAD (d, matrix, nMatrix, x1, y1, x2, y2);
n++;
}
else
{
- pClip = w->region->rects;
+ pClip = clip->rects;
+
+ if (((n + nClip) * vSize * 4) > w->vertexSize)
+ {
+ if (!moreWindowVertices (w, (n + nClip) * vSize * 4))
+ return;
+
+ d = w->vertices + (n * vSize * 4);
+ }
while (nClip--)
{
- clip.x1 = pClip->x1 - w->attrib.x;
- clip.y1 = pClip->y1 - w->attrib.y;
- clip.x2 = pClip->x2 - w->attrib.x;
- clip.y2 = pClip->y2 - w->attrib.y;
+ cbox = *pClip;
pClip++;
- if (clip.x1 < x1)
- clip.x1 = x1;
- if (clip.y1 < y1)
- clip.y1 = y1;
- if (clip.x2 > x2)
- clip.x2 = x2;
- if (clip.y2 > y2)
- clip.y2 = y2;
+ if (cbox.x1 < x1)
+ cbox.x1 = x1;
+ if (cbox.y1 < y1)
+ cbox.y1 = y1;
+ if (cbox.x2 > x2)
+ cbox.x2 = x2;
+ if (cbox.y2 > y2)
+ cbox.y2 = y2;
- if (clip.x1 < clip.x2 && clip.y1 < clip.y2)
+ if (cbox.x1 < cbox.x2 && cbox.y1 < cbox.y2)
{
- if ((n << 4) == dataSize)
- {
- dataSize <<= 2;
- data = realloc (data,
- sizeof (GLfloat) * dataSize);
- if (!data)
- return FALSE;
-
- d = data + (n * 16);
- }
-
- ADD_BOX (d, w, &clip);
+ ADD_QUAD (d, matrix, nMatrix,
+ cbox.x1, cbox.y1, cbox.x2, cbox.y2);
n++;
}
@@ -397,13 +390,78 @@ paintWindow (CompWindow *w,
}
}
}
+ w->vCount = n * 4;
+ }
+}
+
+void
+drawWindowGeometry (CompWindow *w)
+{
+ int texUnit = w->texUnits;
+ int currentTexUnit = 0;
+ int stride = (1 + texUnit) * 2;
+ GLfloat *vertices = w->vertices + (stride - 2);
+
+ stride *= sizeof (GLfloat);
+
+ glVertexPointer (2, GL_FLOAT, stride, vertices);
+
+ while (texUnit--)
+ {
+ if (texUnit != currentTexUnit)
+ {
+ w->screen->clientActiveTexture (GL_TEXTURE0_ARB + texUnit);
+ currentTexUnit = texUnit;
+ }
+ vertices -= 2;
+ glTexCoordPointer (2, GL_FLOAT, stride, vertices);
}
- if (n)
+ glDrawArrays (GL_QUADS, 0, w->vCount);
+}
+
+Bool
+paintWindow (CompWindow *w,
+ const WindowPaintAttrib *attrib,
+ Region region,
+ unsigned int mask)
+{
+ GLushort opacity;
+
+ if (mask & PAINT_WINDOW_SOLID_MASK)
+ {
+ if (w->alpha)
+ return FALSE;
+
+ opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
+ if (opacity != OPAQUE)
+ return FALSE;
+ }
+ else if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
+ {
+ opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
+ if (!w->alpha && opacity == OPAQUE)
+ return FALSE;
+ }
+ else
{
- glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, data);
- glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 4, data + 2);
+ opacity = MULTIPLY_USHORT (w->opacity, attrib->opacity);
+ if (w->alpha || opacity != OPAQUE)
+ mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
+ else
+ mask |= PAINT_WINDOW_SOLID_MASK;
+ }
+
+ if (!w->pixmap)
+ bindWindow (w);
+
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+ region = &infiniteRegion;
+ w->vCount = 0;
+ (*w->screen->addWindowGeometry) (w, &w->matrix, 1, w->region, region);
+ if (w->vCount)
+ {
if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
{
glEnable (GL_BLEND);
@@ -416,22 +474,25 @@ paintWindow (CompWindow *w,
glPushMatrix ();
- if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
+ if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
{
glTranslatef (w->attrib.x + attrib->xTranslate,
w->attrib.y + attrib->yTranslate, 0.0f);
glScalef (attrib->xScale, attrib->yScale, 0.0f);
+ glTranslatef (-w->attrib.x, -w->attrib.y, 0.0f);
enableTexture (w->screen, &w->texture, COMP_TEXTURE_FILTER_GOOD);
}
+ else if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
+ {
+ enableTexture (w->screen, &w->texture, COMP_TEXTURE_FILTER_GOOD);
+ }
else
{
- glTranslatef (w->attrib.x, w->attrib.y, 0.0f);
-
enableTexture (w->screen, &w->texture, COMP_TEXTURE_FILTER_FAST);
}
- glDrawArrays (GL_QUADS, 0, n * 4);
+ (*w->screen->drawWindowGeometry) (w);
disableTexture (&w->texture);
@@ -448,8 +509,6 @@ paintWindow (CompWindow *w,
}
}
- free (data);
-
return TRUE;
}
@@ -491,26 +550,26 @@ paintBackground (CompScreen *s,
n = nBox;
while (n--)
{
- *d++ = bg->dx * pBox->x1;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y2);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x1, pBox->y2);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x1, pBox->y2);
*d++ = pBox->x1;
*d++ = pBox->y2;
- *d++ = bg->dx * pBox->x2;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y2);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x2, pBox->y2);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x2, pBox->y2);
*d++ = pBox->x2;
*d++ = pBox->y2;
- *d++ = bg->dx * pBox->x2;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y1);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x2, pBox->y1);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x2, pBox->y1);
*d++ = pBox->x2;
*d++ = pBox->y1;
- *d++ = bg->dx * pBox->x1;
- *d++ = bg->dy * (s->backgroundHeight - pBox->y1);
+ *d++ = COMP_TEX_COORD_X (&bg->matrix, pBox->x1, pBox->y1);
+ *d++ = COMP_TEX_COORD_Y (&bg->matrix, pBox->x1, pBox->y1);
*d++ = pBox->x1;
*d++ = pBox->y1;