コード例 #1
0
static Bool
enableFragmentProgramAndDrawGeometry (CompWindow	   *w,
				      CompTexture	   *texture,
				      const FragmentAttrib *attrib,
				      int		   filter,
				      unsigned int	   mask)
{
    FragmentAttrib fa = *attrib;
    CompScreen     *s = w->screen;
    Bool	   blending;

    if (s->canDoSaturated && attrib->saturation != COLOR)
    {
	int param, function;

	param    = allocFragmentParameters (&fa, 1);
	function = getSaturateFragmentFunction (s, texture, param);

	addFragmentFunction (&fa, function);

	(*s->programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB, param,
				     RED_SATURATION_WEIGHT,
				     GREEN_SATURATION_WEIGHT,
				     BLUE_SATURATION_WEIGHT,
				     attrib->saturation / 65535.0f);
    }

    if (!enableFragmentAttrib (s, &fa, &blending))
	return FALSE;

    enableTexture (s, texture, filter);

    if (mask & PAINT_WINDOW_BLEND_MASK)
    {
	if (blending)
	    glEnable (GL_BLEND);

	if (attrib->opacity != OPAQUE || attrib->brightness != BRIGHT)
	{
	    GLushort color;

	    color = (attrib->opacity * attrib->brightness) >> 16;

	    screenTexEnvMode (s, GL_MODULATE);
	    glColor4us (color, color, color, attrib->opacity);

	    (*w->drawWindowGeometry) (w);

	    glColor4usv (defaultColor);
	    screenTexEnvMode (s, GL_REPLACE);
	}
	else
	{
コード例 #2
0
ファイル: particle.c プロジェクト: Elive/ecomp
void
drawParticles(CompScreen *s, CompWindow *w, ParticleSystem *ps)
{
   glPushMatrix();
   if (w)
     glTranslated(WIN_X(w) - ps->x, WIN_Y(w) - ps->y, 0);

   glEnable(GL_BLEND);
   if (ps->tex)
     {
        glBindTexture(GL_TEXTURE_2D, ps->tex);
        glEnable(GL_TEXTURE_2D);
     }
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

   int i;
   Particle *part;

   /* Check that the cache is big enough */
   if (ps->numParticles > ps->vertex_cache_count)
     {
        ps->vertices_cache =
          realloc(ps->vertices_cache,
                  ps->numParticles * 4 * 3 * sizeof(GLfloat));
        ps->vertex_cache_count = ps->numParticles;
     }

   if (ps->numParticles > ps->coords_cache_count)
     {
        ps->coords_cache =
          realloc(ps->coords_cache,
                  ps->numParticles * 4 * 2 * sizeof(GLfloat));
        ps->coords_cache_count = ps->numParticles;
     }

   if (ps->numParticles > ps->color_cache_count)
     {
        ps->colors_cache =
          realloc(ps->colors_cache,
                  ps->numParticles * 4 * 4 * sizeof(GLfloat));
        ps->color_cache_count = ps->numParticles;
     }

   if (ps->darken > 0)
     {
        if (ps->dcolors_cache_count < ps->numParticles)
          {
             ps->dcolors_cache =
               realloc(ps->dcolors_cache,
                       ps->numParticles * 4 * 4 * sizeof(GLfloat));
             ps->dcolors_cache_count = ps->numParticles;
          }
     }

   GLfloat *dcolors = ps->dcolors_cache;
   GLfloat *vertices = ps->vertices_cache;
   GLfloat *coords = ps->coords_cache;
   GLfloat *colors = ps->colors_cache;

   int numActive = 0;

   for (i = 0; i < ps->numParticles; i++)
     {
        part = &ps->particles[i];
        if (part->life > 0.0f)
          {
             numActive += 4;

             float w = part->width / 2;
             float h = part->height / 2;

             w += (w * part->w_mod) * part->life;
             h += (h * part->h_mod) * part->life;

             vertices[0] = part->x - w;
             vertices[1] = part->y - h;
             vertices[2] = part->z;

             vertices[3] = part->x - w;
             vertices[4] = part->y + h;
             vertices[5] = part->z;

             vertices[6] = part->x + w;
             vertices[7] = part->y + h;
             vertices[8] = part->z;

             vertices[9] = part->x + w;
             vertices[10] = part->y - h;
             vertices[11] = part->z;

             vertices += 12;

             coords[0] = 0.0;
             coords[1] = 0.0;

             coords[2] = 0.0;
             coords[3] = 1.0;

             coords[4] = 1.0;
             coords[5] = 1.0;

             coords[6] = 1.0;
             coords[7] = 0.0;

             coords += 8;

             colors[0] = part->r;
             colors[1] = part->g;
             colors[2] = part->b;
             colors[3] = part->life * part->a;
             colors[4] = part->r;
             colors[5] = part->g;
             colors[6] = part->b;
             colors[7] = part->life * part->a;
             colors[8] = part->r;
             colors[9] = part->g;
             colors[10] = part->b;
             colors[11] = part->life * part->a;
             colors[12] = part->r;
             colors[13] = part->g;
             colors[14] = part->b;
             colors[15] = part->life * part->a;

             colors += 16;

             if (ps->darken > 0)
               {
                  dcolors[0] = part->r;
                  dcolors[1] = part->g;
                  dcolors[2] = part->b;
                  dcolors[3] = part->life * part->a * ps->darken;
                  dcolors[4] = part->r;
                  dcolors[5] = part->g;
                  dcolors[6] = part->b;
                  dcolors[7] = part->life * part->a * ps->darken;
                  dcolors[8] = part->r;
                  dcolors[9] = part->g;
                  dcolors[10] = part->b;
                  dcolors[11] = part->life * part->a * ps->darken;
                  dcolors[12] = part->r;
                  dcolors[13] = part->g;
                  dcolors[14] = part->b;
                  dcolors[15] = part->life * part->a * ps->darken;

                  dcolors += 16;
               }
          }
     }

   glEnableClientState(GL_COLOR_ARRAY);

   glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), ps->coords_cache);
   glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), ps->vertices_cache);

   // darken the background
   if (ps->darken > 0)
     {
        glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
        glColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), ps->dcolors_cache);
        glDrawArrays(GL_QUADS, 0, numActive);
     }
   // draw particles
   glBlendFunc(GL_SRC_ALPHA, ps->blendMode);

   glColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), ps->colors_cache);

   glDrawArrays(GL_QUADS, 0, numActive);

   glDisableClientState(GL_COLOR_ARRAY);

   glPopMatrix();
   glColor4usv(defaultColor);
   screenTexEnvMode(s, GL_REPLACE);
   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
}
コード例 #3
0
ファイル: group-paint.c プロジェクト: jordigh/fusilli
/*
 * groupDrawWindow
 *
 */
Bool
groupDrawWindow (CompWindow           *w,
                 const CompTransform  *transform,
                 const FragmentAttrib *attrib,
                 Region               region,
                 unsigned int         mask)
{
	Bool status;
	CompScreen *s = w->screen;

	GROUP_WINDOW (w);
	GROUP_SCREEN (s);

	if (gw->group && (gw->group->nWins > 1) && gw->glowQuads)
	{
		if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
			region = &infiniteRegion;

		if (region->numRects)
		{
			REGION box;
			int i;

			box.rects = &box.extents;
			box.numRects = 1;

			w->vCount = w->indexCount = 0;

			for (i = 0; i < NUM_GLOWQUADS; i++)
			{
				box.extents = gw->glowQuads[i].box;

				if (box.extents.x1 < box.extents.x2 &&
				    box.extents.y1 < box.extents.y2)
				{
					(*s->addWindowGeometry)(w, &gw->glowQuads[i].matrix,
					                        1, &box, region);
				}
			}

			if (w->vCount)
			{
				FragmentAttrib fAttrib = *attrib;
				GLushort average;
				GLushort color[3] = {gw->group->color[0],
					             gw->group->color[1],
					             gw->group->color[2]};

				/* Apply brightness to color. */
				color[0] *= (float)attrib->brightness / BRIGHT;
				color[1] *= (float)attrib->brightness / BRIGHT;
				color[2] *= (float)attrib->brightness / BRIGHT;

				/* Apply saturation to color. */
				average = (color[0] + color[1] + color[2]) / 3;
				color[0] = average + (color[0] - average) *
				           attrib->saturation / COLOR;
				color[1] = average + (color[1] - average) *
				           attrib->saturation / COLOR;
				color[2] = average + (color[2] - average) *
				           attrib->saturation / COLOR;

				fAttrib.opacity = OPAQUE;
				fAttrib.saturation = COLOR;
				fAttrib.brightness = BRIGHT;

				screenTexEnvMode (s, GL_MODULATE);
				glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glColor4us (color[0], color[1], color[2], attrib->opacity);

				/* we use PAINT_WINDOW_TRANSFORMED_MASK here to force
				   the usage of a good texture filter */
				(*s->drawWindowTexture)(w, &gs->glowTexture, &fAttrib,
				                        mask | PAINT_WINDOW_BLEND_MASK |
				                        PAINT_WINDOW_TRANSLUCENT_MASK |
				                        PAINT_WINDOW_TRANSFORMED_MASK);

				glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
				screenTexEnvMode (s, GL_REPLACE);
				glColor4usv (defaultColor);
			}
		}
	}

	UNWRAP (gs, s, drawWindow);
	status = (*s->drawWindow)(w, transform, attrib, region, mask);
	WRAP (gs, s, drawWindow, groupDrawWindow);

	return status;
}
コード例 #4
0
static void
drawParticles (CompScreen * s, ParticleSystem * ps)
{
    glPushMatrix ();

    glEnable (GL_BLEND);
    if (ps->tex)
    {
	glBindTexture (GL_TEXTURE_2D, ps->tex);
	glEnable (GL_TEXTURE_2D);
    }
    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    /* Check that the cache is big enough */
    if (ps->hardLimit > ps->vertex_cache_count)
    {
	ps->vertices_cache =
	    realloc (ps->vertices_cache,
		    ps->hardLimit * 4 * 3 * sizeof (GLfloat));
	ps->vertex_cache_count = ps->hardLimit;
    }

    if (ps->hardLimit > ps->coords_cache_count)
    {
	ps->coords_cache =
	    realloc (ps->coords_cache,
		    ps->hardLimit * 4 * 2 * sizeof (GLfloat));
	ps->coords_cache_count = ps->hardLimit;
    }

    if (ps->hardLimit > ps->color_cache_count)
    {
	ps->colors_cache =
	    realloc (ps->colors_cache,
		    ps->hardLimit * 4 * 4 * sizeof (GLfloat));
	ps->color_cache_count = ps->hardLimit;
    }

    if (ps->darken > 0)
    {
	if (ps->dcolors_cache_count < ps->hardLimit)
	{
	    ps->dcolors_cache =
		realloc (ps->dcolors_cache,
			ps->hardLimit * 4 * 4 * sizeof (GLfloat));
	    ps->dcolors_cache_count = ps->hardLimit;
	}
    }

    GLfloat *dcolors  = ps->dcolors_cache;
    GLfloat *vertices = ps->vertices_cache;
    GLfloat *coords   = ps->coords_cache;
    GLfloat *colors   = ps->colors_cache;

    int cornersSize = sizeof (GLfloat) * 8;
    int colorSize   = sizeof (GLfloat) * 4;

    GLfloat cornerCoords[8] = {0.0, 0.0,
			       0.0, 1.0,
			       1.0, 1.0,
			       1.0, 0.0};

    int numActive = 0;

    Particle *part = ps->particles;
    int i;
    for (i = 0; i < ps->hardLimit; i++, part++)
    {
	if (part->t > 0.0f)
	{
	    numActive += 4;

	    float cOff = part->s / 2.;		//Corner offset from center

	    if (part->t > ps->tnew)		//New particles start larger
		cOff += (part->snew - part->s) * (part->t - ps->tnew)
			/ (1. - ps->tnew) / 2.;
	    else if (part->t < ps->told)	//Old particles shrink
		cOff -= part->s * (ps->told - part->t) / ps->told / 2.;

	    //Offsets after rotation of Texture
	    float offA = cOff * (cos (part->phi) - sin (part->phi));
	    float offB = cOff * (cos (part->phi) + sin (part->phi));

	    vertices[0] = part->x - offB;
	    vertices[1] = part->y - offA;
	    vertices[2] = 0;

	    vertices[3] = part->x - offA;
	    vertices[4] = part->y + offB;
	    vertices[5] = 0;

	    vertices[6] = part->x + offB;
	    vertices[7] = part->y + offA;
	    vertices[8] = 0;

	    vertices[9]  = part->x + offA;
	    vertices[10] = part->y - offB;
	    vertices[11] = 0;

	    vertices += 12;

	    memcpy (coords, cornerCoords, cornersSize);

	    coords += 8;

	    colors[0] = part->c[0];
	    colors[1] = part->c[1];
	    colors[2] = part->c[2];

	    if (part->t > ps->tnew)		//New particles start at a == 1
		colors[3] = part->a + (1. - part->a) * (part->t - ps->tnew)
					/ (1. - ps->tnew);
	    else if (part->t < ps->told)	//Old particles fade to a = 0
		colors[3] = part->a * part->t / ps->told;
	    else				//The others have their own a
		colors[3] = part->a;

	    memcpy (colors + 4, colors, colorSize);
	    memcpy (colors + 8, colors, colorSize);
	    memcpy (colors + 12, colors, colorSize);

	    colors += 16;

	    if (ps->darken > 0)
	    {
		dcolors[0] = colors[0];
		dcolors[1] = colors[1];
		dcolors[2] = colors[2];
		dcolors[3] = colors[3] * ps->darken;
		memcpy (dcolors + 4, dcolors, colorSize);
		memcpy (dcolors + 8, dcolors, colorSize);
		memcpy (dcolors + 12, dcolors, colorSize);

		dcolors += 16;
	    }
	}
    }

    glEnableClientState (GL_COLOR_ARRAY);

    glTexCoordPointer (2, GL_FLOAT, 2 * sizeof (GLfloat), ps->coords_cache);
    glVertexPointer (3, GL_FLOAT, 3 * sizeof (GLfloat), ps->vertices_cache);

    // darken the background
    if (ps->darken > 0)
    {
	glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
	glColorPointer (4, GL_FLOAT, 4 * sizeof (GLfloat), ps->dcolors_cache);
	glDrawArrays (GL_QUADS, 0, numActive);
    }
    // draw particles
    glBlendFunc (GL_SRC_ALPHA, ps->blendMode);

    glColorPointer (4, GL_FLOAT, 4 * sizeof (GLfloat), ps->colors_cache);

    glDrawArrays (GL_QUADS, 0, numActive);

    glDisableClientState (GL_COLOR_ARRAY);

    glPopMatrix ();
    glColor4usv (defaultColor);
    screenTexEnvMode (s, GL_REPLACE);
    glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glDisable (GL_TEXTURE_2D);
    glDisable (GL_BLEND);
}
コード例 #5
0
ファイル: thumbnail.c プロジェクト: noodlylight/fusilli
static void
thumbPaintThumb (CompScreen          *s,
                 Thumbnail           *t,
                 const CompTransform *transform)
{
	AddWindowGeometryProc oldAddWindowGeometry;
	CompWindow            *w = t->win;
	int wx = t->x;
	int wy = t->y;
	float width  = t->width;
	float height = t->height;
	WindowPaintAttrib sAttrib;
	unsigned int mask = PAINT_WINDOW_TRANSFORMED_MASK |
	                    PAINT_WINDOW_TRANSLUCENT_MASK;

	THUMB_SCREEN (s);

	if (!w)
		return;

	sAttrib = w->paint;

	if (t->textData)
		height += t->textData->height + TEXT_DISTANCE;

	/* Wrap drawWindowGeometry to make sure the general
	   drawWindowGeometry function is used */
	oldAddWindowGeometry = s->addWindowGeometry;
	s->addWindowGeometry = addWindowGeometry;

	if (w->texture->pixmap)
	{
		int off = t->offset;
		GLenum filter = display.textureFilter;
		FragmentAttrib fragment;
		CompTransform wTransform = *transform;

		glEnable (GL_BLEND);
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		glDisableClientState (GL_TEXTURE_COORD_ARRAY);

		const BananaValue *
		option_window_like = bananaGetOption (bananaIndex,
		                                      "window_like",
		                                      s->screenNum);

		if (option_window_like->b)
		{
			glColor4f (1.0, 1.0, 1.0, t->opacity);
			enableTexture (s, &ts->windowTexture, COMP_TEXTURE_FILTER_GOOD);
		}
		else
		{
			unsigned short color[] = { 0, 0, 0, 0 };

			const BananaValue *
			option_thumb_color = bananaGetOption (bananaIndex,
			                                      "thumb_color",
			                                      s->screenNum);

			stringToColor (option_thumb_color->s, color);

			glColor4us (color[0],
			            color[1],
			            color[2],
			            color[3] * t->opacity);

			enableTexture (s, &ts->glowTexture, COMP_TEXTURE_FILTER_GOOD);
		}

		glBegin (GL_QUADS);

		glTexCoord2f (1, 0);
		glVertex2f (wx, wy);
		glVertex2f (wx, wy + height);
		glVertex2f (wx + width, wy + height);
		glVertex2f (wx + width, wy);

		glTexCoord2f (0, 1);
		glVertex2f (wx - off, wy - off);
		glTexCoord2f (0, 0);
		glVertex2f (wx - off, wy);
		glTexCoord2f (1, 0);
		glVertex2f (wx, wy);
		glTexCoord2f (1, 1);
		glVertex2f (wx, wy - off);

		glTexCoord2f (1, 1);
		glVertex2f (wx + width, wy - off);
		glTexCoord2f (1, 0);
		glVertex2f (wx + width, wy);
		glTexCoord2f (0, 0);
		glVertex2f (wx + width + off, wy);
		glTexCoord2f (0, 1);
		glVertex2f (wx + width + off, wy - off);

		glTexCoord2f (0, 0);
		glVertex2f (wx - off, wy + height);
		glTexCoord2f (0, 1);
		glVertex2f (wx - off, wy + height + off);
		glTexCoord2f (1, 1);
		glVertex2f (wx, wy + height + off);
		glTexCoord2f (1, 0);
		glVertex2f (wx, wy + height);

		glTexCoord2f (1, 0);
		glVertex2f (wx + width, wy + height);
		glTexCoord2f (1, 1);
		glVertex2f (wx + width, wy + height + off);
		glTexCoord2f (0, 1);
		glVertex2f (wx + width + off, wy + height + off);
		glTexCoord2f (0, 0);
		glVertex2f (wx + width + off, wy + height);

		glTexCoord2f (1, 1);
		glVertex2f (wx, wy - off);
		glTexCoord2f (1, 0);
		glVertex2f (wx, wy);
		glTexCoord2f (1, 0);
		glVertex2f (wx + width, wy);
		glTexCoord2f (1, 1);
		glVertex2f (wx + width, wy - off);

		glTexCoord2f (1, 0);
		glVertex2f (wx, wy + height);
		glTexCoord2f (1, 1);
		glVertex2f (wx, wy + height + off);
		glTexCoord2f (1, 1);
		glVertex2f (wx + width, wy + height + off);
		glTexCoord2f (1, 0);
		glVertex2f (wx + width, wy + height);

		glTexCoord2f (0, 0);
		glVertex2f (wx - off, wy);
		glTexCoord2f (0, 0);
		glVertex2f (wx - off, wy + height);
		glTexCoord2f (1, 0);
		glVertex2f (wx, wy + height);
		glTexCoord2f (1, 0);
		glVertex2f (wx, wy);

		glTexCoord2f (1, 0);
		glVertex2f (wx + width, wy);
		glTexCoord2f (1, 0);
		glVertex2f (wx + width, wy + height);
		glTexCoord2f (0, 0);
		glVertex2f (wx + width + off, wy + height);
		glTexCoord2f (0, 0);
		glVertex2f (wx + width + off, wy);

		glEnd ();

		if (option_window_like->b)
		{
			disableTexture (s, &ts->windowTexture);
		}
		else
		{
			disableTexture (s, &ts->glowTexture);
		}

		glColor4usv (defaultColor);

		glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

		if (t->textData)
		{
			float ox = 0.0;

			if (t->textData->width < width)
				ox = (width - (int)t->textData->width) / 2.0;

			textDrawText (s, t->textData, wx + ox, wy + height, t->opacity);
		}

		glEnableClientState (GL_TEXTURE_COORD_ARRAY);
		glDisable (GL_BLEND);

		screenTexEnvMode (s, GL_REPLACE);

		glColor4usv (defaultColor);

		sAttrib.opacity *= t->opacity;
		sAttrib.yScale = t->scale;
		sAttrib.xScale = t->scale;

		sAttrib.xTranslate = wx - w->attrib.x + w->input.left * sAttrib.xScale;
		sAttrib.yTranslate = wy - w->attrib.y + w->input.top * sAttrib.yScale;

		const BananaValue *
		option_mipmap = bananaGetOption (bananaIndex,
		                                 "mipmap",
		                                 s->screenNum);

		if (option_mipmap->b)
			display.textureFilter = GL_LINEAR_MIPMAP_LINEAR;

		initFragmentAttrib (&fragment, &sAttrib);

		matrixTranslate (&wTransform, w->attrib.x, w->attrib.y, 0.0f);
		matrixScale (&wTransform, sAttrib.xScale, sAttrib.yScale, 1.0f);
		matrixTranslate (&wTransform,
		                 sAttrib.xTranslate / sAttrib.xScale - w->attrib.x,
		                 sAttrib.yTranslate / sAttrib.yScale - w->attrib.y,
		                 0.0f);

		glPushMatrix ();
		glLoadMatrixf (wTransform.m);
		(*s->drawWindow) (w, &wTransform, &fragment, &infiniteRegion, mask);
		glPopMatrix ();

		display.textureFilter = filter;
	}

	s->addWindowGeometry = oldAddWindowGeometry;
}
コード例 #6
0
static void
NEGDrawWindowTexture (CompWindow           *w,
		      CompTexture          *texture,
		      const FragmentAttrib *attrib,
		      unsigned int         mask)
{
    int filter;

    NEG_SCREEN (w->screen);
    NEG_WINDOW (w);

    /* only negate window contents; that's the only case
       where w->texture->name == texture->name */
    if (nw->isNeg && (texture->name == w->texture->name))
    {
	if (w->screen->fragmentProgram)
	{
	    FragmentAttrib fa = *attrib;
	    int            function;

	    function = getNegFragmentFunction (w->screen, texture, w->alpha);
	    if (function)
		addFragmentFunction (&fa, function);

	    UNWRAP (ns, w->screen, drawWindowTexture);
	    (*w->screen->drawWindowTexture) (w, texture, &fa, mask);
	    WRAP (ns, w->screen, drawWindowTexture, NEGDrawWindowTexture);
	}
	else
	{
	    /* this is for the most part taken from paint.c */

	    if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
		filter = w->screen->filter[WINDOW_TRANS_FILTER];
	    else if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
		filter = w->screen->filter[SCREEN_TRANS_FILTER];
	    else
		filter = w->screen->filter[NOTHING_TRANS_FILTER];

	    /* if we can addjust saturation, even if it's just on and off */
	    if (w->screen->canDoSaturated && attrib->saturation != COLOR)
	    {
		GLfloat constant[4];

		/* if the paint mask has this set we want to blend */
		if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
		    glEnable (GL_BLEND);

		/* enable the texture */
		enableTexture (w->screen, texture, filter);

		/* texture combiner */
		glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PRIMARY_COLOR);

		/* negate */
		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
			   GL_ONE_MINUS_SRC_COLOR);

		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);

		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);

		glColor4f (1.0f, 1.0f, 1.0f, 0.5f);

		/* make another texture active */
		(*w->screen->activeTexture) (GL_TEXTURE1_ARB);

		/* enable that texture */
		enableTexture (w->screen, texture, filter);

		glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);

		/* if we can do saturation that is in between min and max */
		if (w->screen->canDoSlightlySaturated && attrib->saturation > 0)
		{
		    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);

    		    constant[0] = 0.5f + 0.5f * RED_SATURATION_WEIGHT;
		    constant[1] = 0.5f + 0.5f * GREEN_SATURATION_WEIGHT;
		    constant[2] = 0.5f + 0.5f * BLUE_SATURATION_WEIGHT;
		    constant[3] = 1.0;

		    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);

    		    /* mark another texture active */
		    (*w->screen->activeTexture) (GL_TEXTURE2_ARB);

		    /* enable that texture */
    		    enableTexture (w->screen, texture, filter);

	    	    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT);

		    /* negate */
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
			       GL_ONE_MINUS_SRC_COLOR);

		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);

		    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);

    		    /* color constant */
		    constant[3] = attrib->saturation / 65535.0f;

		    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);

    		    /* if we are not opaque or not fully bright */
		    if (attrib->opacity < OPAQUE ||
			attrib->brightness != BRIGHT)
		    {
			/* activate a new texture */
			(*w->screen->activeTexture) (GL_TEXTURE3_ARB);

			/* enable that texture */
			enableTexture (w->screen, texture, filter);

			/* color constant */
			constant[3] = attrib->opacity / 65535.0f;
			constant[0] = constant[1] = constant[2] =
			              constant[3] * attrib->brightness /
				      65535.0f;

			glTexEnvfv(GL_TEXTURE_ENV,
				   GL_TEXTURE_ENV_COLOR, constant);

			glTexEnvf(GL_TEXTURE_ENV,
				  GL_TEXTURE_ENV_MODE, GL_COMBINE);

			glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
			glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
			glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
			glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
				   GL_SRC_COLOR);
			glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB,
				   GL_SRC_COLOR);

			glTexEnvf (GL_TEXTURE_ENV,
				   GL_COMBINE_ALPHA, GL_MODULATE);
			glTexEnvf(GL_TEXTURE_ENV,
				  GL_SOURCE0_ALPHA, GL_PREVIOUS);
			glTexEnvf(GL_TEXTURE_ENV,
				  GL_SOURCE1_ALPHA, GL_CONSTANT);
			glTexEnvf(GL_TEXTURE_ENV,
				  GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
			glTexEnvf(GL_TEXTURE_ENV,
				  GL_OPERAND1_ALPHA, GL_SRC_ALPHA);

			/* draw the window geometry */
			(*w->drawWindowGeometry) (w);

			/* disable the current texture */
			disableTexture (w->screen, texture);

			/* set texture mode back to replace */
			glTexEnvi (GL_TEXTURE_ENV,
				   GL_TEXTURE_ENV_MODE, GL_REPLACE);

			/* re-activate last texture */
			(*w->screen->activeTexture) (GL_TEXTURE2_ARB);
		    }
		    else
		    {
			/* fully opaque and bright */

			/* draw the window geometry */
			(*w->drawWindowGeometry) (w);
		    }

		    /* disable the current texture */
		    disableTexture (w->screen, texture);

	    	    /* set the texture mode back to replace */
		    glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

		    /* re-activate last texture */
		    (*w->screen->activeTexture) (GL_TEXTURE1_ARB);
		}
		else
		{
		    /* fully saturated or fully unsaturated */

		    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
    		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);

    		    /* color constant */
		    constant[3] = attrib->opacity / 65535.0f;
		    constant[0] = constant[1] = constant[2] =
				  constant[3] * attrib->brightness / 65535.0f;

		    constant[0] =
			0.5f + 0.5f * RED_SATURATION_WEIGHT * constant[0];
		    constant[1] =
			0.5f + 0.5f * GREEN_SATURATION_WEIGHT * constant[1];
		    constant[2] =
			0.5f + 0.5f * BLUE_SATURATION_WEIGHT * constant[2];

		    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);

    		    /* draw the window geometry */
		    (*w->drawWindowGeometry) (w);
		}

		/* disable the current texture */
		disableTexture (w->screen, texture);

		/* set the texture mode back to replace */
		glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

		/* re-activate last texture */
		(*w->screen->activeTexture) (GL_TEXTURE0_ARB);

		/* disable that texture */
		disableTexture (w->screen, texture);

		/* set the default color */
		glColor4usv (defaultColor);

		/* set screens texture mode back to replace */
		screenTexEnvMode (w->screen, GL_REPLACE);

		/* if it's a translucent window, disable blending */
		if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
		    glDisable (GL_BLEND);
	    }
	    else
	    {
		/* no saturation adjustments */

		/* enable the current texture */
		enableTexture (w->screen, texture, filter);

		glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);

		/* negate */
		glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB,
			  GL_ONE_MINUS_SRC_COLOR);

		/* we are not opaque or fully bright */
		if ((mask & PAINT_WINDOW_TRANSLUCENT_MASK) ||
		    attrib->brightness != BRIGHT)
		{
		    GLfloat constant[4];

		    /* enable blending */
		    glEnable (GL_BLEND);

    		    /* color constant */
		    constant[3] = attrib->opacity / 65535.0f;
		    constant[0] = constant[3] * attrib->brightness / 65535.0f;
		    constant[1] = constant[3] * attrib->brightness / 65535.0f;
		    constant[2] = constant[3] * attrib->brightness / 65535.0f;

		    glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
		    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);

		    /* negate */
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
			       GL_ONE_MINUS_SRC_COLOR);

		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
		    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
		    glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
		    glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);

    		    /* draw the window geometry */
		    (*w->drawWindowGeometry) (w);

		    /* disable blending */
		    glDisable (GL_BLEND);
		}
		else
		{
		    /* no adjustments to saturation, brightness or opacity */

		    /* draw the window geometry */
		    (*w->drawWindowGeometry) (w);
		}

		/* disable the current texture */
		disableTexture (w->screen, texture);

		/* set the screens texture mode back to replace */
		screenTexEnvMode (w->screen, GL_REPLACE);
	    }
	}
    }
    else
    {
	/* not negative */
	UNWRAP (ns, w->screen, drawWindowTexture);
	(*w->screen->drawWindowTexture) (w, texture, attrib, mask);
	WRAP (ns, w->screen, drawWindowTexture, NEGDrawWindowTexture);
    }
}