xserver-multidpi/hw/xgl/xgloffscreen.c

294 lines
7.1 KiB
C
Raw Normal View History

2004-11-05 00:19:13 +01:00
/*
2004-11-05 14:26:07 +01:00
* Copyright © 2004 David Reveman
2004-11-05 00:19:13 +01:00
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
2005-01-26 11:58:52 +01:00
* appear in supporting documentation, and that the name of
2004-11-05 00:19:13 +01:00
* David Reveman not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior permission.
* David Reveman makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
2005-01-26 11:58:52 +01:00
* Author: David Reveman <davidr@novell.com>
2004-11-05 00:19:13 +01:00
*/
#include "xgl.h"
static glitz_drawable_buffer_t _buffers[] = {
GLITZ_DRAWABLE_BUFFER_BACK_COLOR,
GLITZ_DRAWABLE_BUFFER_FRONT_COLOR
};
2005-01-26 11:58:52 +01:00
#define MAX_OFFSCREEN_LEVEL 8
static Bool
xglOffscreenCreate (xglAreaPtr pArea)
{
return TRUE;
}
2004-11-05 00:19:13 +01:00
static Bool
2005-01-26 11:58:52 +01:00
xglOffscreenMoveIn (xglAreaPtr pArea,
pointer closure)
2004-11-05 00:19:13 +01:00
{
2005-01-26 11:58:52 +01:00
xglOffscreenPtr pOffscreen = (xglOffscreenPtr) pArea->pRoot->closure;
PixmapPtr pPixmap = (PixmapPtr) closure;
2004-11-05 00:19:13 +01:00
XGL_PIXMAP_PRIV (pPixmap);
if (!xglSyncSurface (&pPixmap->drawable))
FatalError (XGL_SW_FAILURE_STRING);
pPixmapPriv->pArea = pArea;
pPixmapPriv->target = xglPixmapTargetIn;
glitz_surface_attach (pPixmapPriv->surface,
2005-01-26 11:58:52 +01:00
pOffscreen->drawable, pOffscreen->buffer,
2004-11-05 00:19:13 +01:00
pArea->x, pArea->y);
2005-01-26 11:58:52 +01:00
XGL_INCREMENT_PIXMAP_SCORE (pPixmapPriv, 100);
2004-11-05 00:19:13 +01:00
return TRUE;
}
static void
2005-01-26 11:58:52 +01:00
xglOffscreenMoveOut (xglAreaPtr pArea,
pointer closure)
2004-11-05 00:19:13 +01:00
{
2005-01-26 11:58:52 +01:00
PixmapPtr pPixmap = (PixmapPtr) closure;
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
XGL_PIXMAP_PRIV (pPixmap);
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
glitz_surface_detach (pPixmapPriv->surface);
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
pPixmapPriv->pArea = NULL;
pPixmapPriv->target = xglPixmapTargetOut;
2004-11-05 00:19:13 +01:00
}
2005-01-26 11:58:52 +01:00
static int
xglOffscreenCompareScore (xglAreaPtr pArea,
pointer closure1,
pointer closure2)
2004-11-05 00:19:13 +01:00
{
2005-01-26 11:58:52 +01:00
int s1, s2;
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
XGL_PIXMAP_PRIV ((PixmapPtr) closure1);
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
s1 = pPixmapPriv->score;
s2 = XGL_GET_PIXMAP_PRIV ((PixmapPtr) closure2)->score;
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
if (s1 > s2)
XGL_DECREMENT_PIXMAP_SCORE (pPixmapPriv, 10);
2005-04-13 16:27:47 +02:00
if (pPixmapPriv->lock)
return 1;
2005-01-26 11:58:52 +01:00
return s1 - s2;
2004-11-05 00:19:13 +01:00
}
2005-01-26 11:58:52 +01:00
static const xglAreaFuncsRec xglOffscreenAreaFuncs = {
xglOffscreenCreate,
xglOffscreenMoveIn,
xglOffscreenMoveOut,
xglOffscreenCompareScore
};
2004-11-05 00:19:13 +01:00
Bool
xglInitOffscreen (ScreenPtr pScreen,
xglScreenInfoPtr pScreenInfo)
{
xglOffscreenPtr pOffscreen;
glitz_drawable_format_t *format;
XGL_SCREEN_PRIV (pScreen);
2005-01-26 11:58:52 +01:00
pOffscreen = pScreenPriv->pOffscreen;
2004-11-05 00:19:13 +01:00
pScreenPriv->nOffscreen = 0;
format = glitz_drawable_get_format (pScreenPriv->drawable);
/*
* Use back buffer as offscreen area.
*/
if (format->doublebuffer)
{
2005-01-26 11:58:52 +01:00
pOffscreen->drawable = pScreenPriv->drawable;
pOffscreen->format = format;
pOffscreen->buffer = GLITZ_DRAWABLE_BUFFER_BACK_COLOR;
if (xglRootAreaInit (&pOffscreen->rootArea,
MAX_OFFSCREEN_LEVEL,
pScreenInfo->width,
pScreenInfo->height, 0,
(xglAreaFuncsPtr) &xglOffscreenAreaFuncs,
(pointer) pOffscreen))
2004-11-05 00:19:13 +01:00
{
2005-01-26 11:58:52 +01:00
glitz_drawable_reference (pOffscreen->drawable);
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
pScreenPriv->nOffscreen++;
pOffscreen++;
ErrorF ("Initialized %dx%d back buffer offscreen area\n",
pScreenInfo->width, pScreenInfo->height);
2004-11-05 00:19:13 +01:00
}
}
if (nxglPbufferVisuals)
{
2005-01-26 11:58:52 +01:00
glitz_drawable_t *pbuffer;
unsigned int width, height;
int i;
2004-11-05 00:19:13 +01:00
for (i = 0; i < nxglPbufferVisuals; i++)
{
/*
* This can be a bit tricky. I've noticed that when some OpenGL
* drivers can't create an accelerated pbuffer of the size we're
* requesting they create a software one with the correct
* size, but that's not what we want. So if your OpenGL driver
* supports accelerated pbuffers but offscreen drawing is really
* slow, try decrementing these values.
*/
2005-01-26 11:58:52 +01:00
width = 2048;
height = 2048;
do {
pbuffer =
glitz_create_pbuffer_drawable (pScreenPriv->drawable,
xglPbufferVisuals[i].format,
width, height);
width >>= 1;
height >>= 1;
} while (!pbuffer && width);
2004-11-05 00:19:13 +01:00
if (pbuffer)
{
2005-01-26 11:58:52 +01:00
int j = 0;
2004-11-05 00:19:13 +01:00
width = glitz_drawable_get_width (pbuffer);
height = glitz_drawable_get_height (pbuffer);
/*
* No back buffer? only add front buffer.
*/
if (!xglPbufferVisuals[i].format->doublebuffer)
j++;
while (j < 2)
{
2005-01-26 11:58:52 +01:00
pOffscreen->drawable = pbuffer;
pOffscreen->format = xglPbufferVisuals[i].format;
pOffscreen->buffer = _buffers[j];
if (xglRootAreaInit (&pOffscreen->rootArea,
MAX_OFFSCREEN_LEVEL,
width, height, 0,
(xglAreaFuncsPtr)
&xglOffscreenAreaFuncs,
(pointer) pOffscreen))
2004-11-05 00:19:13 +01:00
{
2005-01-26 11:58:52 +01:00
glitz_drawable_reference (pbuffer);
pScreenPriv->nOffscreen++;
pOffscreen++;
ErrorF ("Initialized %dx%d pbuffer offscreen area\n",
width, height);
2004-11-05 00:19:13 +01:00
}
j++;
}
glitz_drawable_destroy (pbuffer);
}
}
}
return TRUE;
}
void
xglFiniOffscreen (ScreenPtr pScreen)
{
2005-01-26 11:58:52 +01:00
int n;
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
XGL_SCREEN_PRIV (pScreen);
n = pScreenPriv->nOffscreen;
while (n--)
{
xglRootAreaFini (&pScreenPriv->pOffscreen[n].rootArea);
glitz_drawable_destroy (pScreenPriv->pOffscreen[n].drawable);
}
pScreenPriv->nOffscreen = 0;
2004-11-05 00:19:13 +01:00
}
Bool
xglFindOffscreenArea (ScreenPtr pScreen,
PixmapPtr pPixmap)
{
xglOffscreenPtr pOffscreen;
int nOffscreen;
glitz_color_format_t *pColor;
XGL_SCREEN_PRIV (pScreen);
XGL_PIXMAP_PRIV (pPixmap);
if (pPixmapPriv->score < 0)
return FALSE;
pColor = &pPixmapPriv->format->color;
pOffscreen = pScreenPriv->pOffscreen;
nOffscreen = pScreenPriv->nOffscreen;
while (nOffscreen--)
{
if (pOffscreen->format->color.red_size >= pColor->red_size &&
pOffscreen->format->color.green_size >= pColor->green_size &&
pOffscreen->format->color.blue_size >= pColor->blue_size &&
pOffscreen->format->color.alpha_size >= pColor->alpha_size)
{
2005-01-26 11:58:52 +01:00
/* Find available area */
if (xglFindArea (pOffscreen->rootArea.pArea,
pPixmap->drawable.width,
pPixmap->drawable.height,
FALSE,
(pointer) pPixmap))
return TRUE;
2004-11-05 00:19:13 +01:00
2005-01-26 11:58:52 +01:00
/* Kicking out area with lower score */
if (xglFindArea (pOffscreen->rootArea.pArea,
pPixmap->drawable.width,
pPixmap->drawable.height,
TRUE,
(pointer) pPixmap))
2004-11-05 00:19:13 +01:00
return TRUE;
}
2005-01-26 11:58:52 +01:00
2004-11-05 00:19:13 +01:00
pOffscreen++;
}
2005-01-26 11:58:52 +01:00
2004-11-05 00:19:13 +01:00
return FALSE;
}
void
2005-01-26 11:58:52 +01:00
xglLeaveOffscreenArea (PixmapPtr pPixmap)
2004-11-05 00:19:13 +01:00
{
2005-01-26 11:58:52 +01:00
XGL_PIXMAP_PRIV (pPixmap);
if (pPixmapPriv->pArea)
xglLeaveArea (pPixmapPriv->pArea);
pPixmapPriv->pArea = NULL;
2004-11-05 00:19:13 +01:00
}