glamor: Create FBOs for pixmaps.

This commit is contained in:
Eric Anholt 2009-08-20 15:28:13 -07:00 committed by Zhigang Gong
parent f92d1478e9
commit 519103565c
5 changed files with 148 additions and 93 deletions

View File

@ -40,6 +40,8 @@
static int glamor_screen_private_key_index; static int glamor_screen_private_key_index;
DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index; DevPrivateKey glamor_screen_private_key = &glamor_screen_private_key_index;
static int glamor_pixmap_private_key_index;
DevPrivateKey glamor_pixmap_private_key = &glamor_pixmap_private_key_index;
/** /**
* glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable. * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable.
@ -63,9 +65,57 @@ glamor_get_drawable_pixmap(DrawablePtr drawable)
static PixmapPtr static PixmapPtr
glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
unsigned int usage_hint) unsigned int usage)
{ {
return fbCreatePixmap(screen, w, h, depth, usage_hint); PixmapPtr pixmap;
glamor_pixmap_private *pixmap_priv;
GLenum format;
if (w > 32767 || h > 32767)
return NullPixmap;
pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
pixmap_priv = glamor_get_pixmap_private(pixmap);
if (w == 0 || h == 0)
return pixmap;
/* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA.
* FBOs, which EXT_fbo forgot to do.
*/
switch (depth) {
case 24:
format = GL_RGB;
break;
default:
format = GL_RGBA;
break;
}
/* Create the texture used to store the pixmap's data. */
glGenTextures(1, &pixmap_priv->tex);
glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0,
format, GL_UNSIGNED_BYTE, NULL);
/* Create a framebuffer object wrapping the texture so that we can render
* to it.
*/
glGenFramebuffersEXT(1, &pixmap_priv->fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D,
pixmap_priv->tex,
0);
screen->ModifyPixmapHeader(pixmap, w, h, 0, 0,
(w * pixmap->drawable.bitsPerPixel + 7) / 8,
NULL);
return pixmap;
} }
static Bool static Bool
@ -96,9 +146,19 @@ glamor_init(ScreenPtr screen)
return FALSE; return FALSE;
dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv); dixSetPrivate(&screen->devPrivates, glamor_screen_private_key, glamor_priv);
if (!dixRequestPrivate(glamor_pixmap_private_key,
sizeof(glamor_pixmap_private))) {
LogMessage(X_WARNING,
"glamor%d: Failed to allocate pixmap private\n",
screen->myNum);
}
glewInit(); glewInit();
if (!GLEW_EXT_framebuffer_object) {
ErrorF("GL_EXT_framebuffer_object required\n");
goto fail;
}
if (!GLEW_ARB_shader_objects) { if (!GLEW_ARB_shader_objects) {
ErrorF("GL_ARB_shader_objects required\n"); ErrorF("GL_ARB_shader_objects required\n");
goto fail; goto fail;

View File

@ -42,17 +42,28 @@
Bool Bool
glamor_set_destination_pixmap(PixmapPtr pixmap) glamor_set_destination_pixmap(PixmapPtr pixmap)
{ {
ScreenPtr screen = pixmap->drawable.pScreen; glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
if (pixmap != screen_pixmap) { if (pixmap_priv == NULL) {
ErrorF("stubbed drawing to non-screen pixmap\n"); ErrorF("no pixmap priv?");
return FALSE; return FALSE;
} }
if (pixmap_priv->fb == 0) {
ScreenPtr screen = pixmap->drawable.pScreen;
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
if (pixmap != screen_pixmap) {
ErrorF("No FBO\n");
return FALSE;
}
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb);
glViewport(0, 0, glViewport(0, 0,
screen_pixmap->drawable.width, pixmap->drawable.width,
screen_pixmap->drawable.height); pixmap->drawable.height);
return TRUE; return TRUE;
} }
@ -75,10 +86,18 @@ void
glamor_set_transform_for_pixmap(PixmapPtr pixmap, glamor_set_transform_for_pixmap(PixmapPtr pixmap,
glamor_transform_uniforms *uniform_locations) glamor_transform_uniforms *uniform_locations)
{ {
ScreenPtr screen = pixmap->drawable.pScreen;
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
glUniform1fARB(uniform_locations->x_bias, -pixmap->drawable.width / 2.0f); glUniform1fARB(uniform_locations->x_bias, -pixmap->drawable.width / 2.0f);
glUniform1fARB(uniform_locations->x_scale, 2.0f / pixmap->drawable.width); glUniform1fARB(uniform_locations->x_scale, 2.0f / pixmap->drawable.width);
glUniform1fARB(uniform_locations->y_bias, -pixmap->drawable.height / 2.0f); glUniform1fARB(uniform_locations->y_bias, -pixmap->drawable.height / 2.0f);
glUniform1fARB(uniform_locations->y_scale, -2.0f / pixmap->drawable.height); if (pixmap == screen_pixmap)
glUniform1fARB(uniform_locations->y_scale,
-2.0f / pixmap->drawable.height);
else
glUniform1fARB(uniform_locations->y_scale,
2.0f / pixmap->drawable.height);
} }
GLint GLint
@ -176,53 +195,38 @@ static void
glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
int w, int h, int leftPad, int format, char *bits) int w, int h, int leftPad, int format, char *bits)
{ {
ScreenPtr screen = drawable->pScreen; ErrorF("stub put_image\n");
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable);
if (screen_pixmap != dest_pixmap) {
fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
} else {
ErrorF("stub put_image\n");
}
} }
static void static void
glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src, glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
DDXPointPtr points, int *widths, int n, int sorted) DDXPointPtr points, int *widths, int n, int sorted)
{ {
ScreenPtr screen = drawable->pScreen;
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable); PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable);
GLenum format, type;
int i;
if (screen_pixmap != dest_pixmap) { switch (drawable->depth) {
fbSetSpans(drawable, gc, src, points, widths, n, sorted); case 24:
} else { case 32:
GLenum format, type; format = GL_BGRA;
int i; type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
default:
ErrorF("Unknown setspans depth %d\n", drawable->depth);
return;
}
switch (drawable->depth) { if (!glamor_set_destination_pixmap(dest_pixmap))
case 24: return;
case 32: for (i = 0; i < n; i++) {
format = GL_BGRA; glRasterPos2i(points[i].x - dest_pixmap->screen_x,
type = GL_UNSIGNED_INT_8_8_8_8_REV; points[i].y - dest_pixmap->screen_y);
break; glDrawPixels(widths[i],
default: 1,
ErrorF("Unknown setspans depth %d\n", drawable->depth); format, type,
return; src);
} src += PixmapBytePad(widths[i], drawable->depth);
if (!glamor_set_destination_pixmap(dest_pixmap))
return;
for (i = 0; i < n; i++) {
glRasterPos2i(points[i].x - dest_pixmap->screen_x,
points[i].y - dest_pixmap->screen_y);
glDrawPixels(widths[i],
1,
format, type,
src);
src += PixmapBytePad(widths[i], drawable->depth);
}
} }
} }
@ -235,9 +239,6 @@ static void
glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n, glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
DDXPointPtr points) DDXPointPtr points)
{ {
ScreenPtr screen = drawable->pScreen;
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable);
xRectangle *rects; xRectangle *rects;
int x1, x2, y1, y2; int x1, x2, y1, y2;
int i; int i;
@ -245,10 +246,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
/* Don't try to do wide lines or non-solid fill style. */ /* Don't try to do wide lines or non-solid fill style. */
if (gc->lineWidth != 0 || gc->lineStyle != LineSolid || if (gc->lineWidth != 0 || gc->lineStyle != LineSolid ||
gc->fillStyle != FillSolid) { gc->fillStyle != FillSolid) {
if (dest_pixmap != screen_pixmap) ErrorF("stub poly_line\n");
fbPolyLine(drawable, gc, mode, n, points);
else
ErrorF("stub poly_line\n");
return; return;
} }
@ -267,10 +265,7 @@ glamor_poly_lines(DrawablePtr drawable, GCPtr gc, int mode, int n,
if (x1 != x2 && y1 != y2) { if (x1 != x2 && y1 != y2) {
xfree(rects); xfree(rects);
if (dest_pixmap != screen_pixmap) ErrorF("stub poly_line\n");
fbPolyLine(drawable, gc, mode, n, points);
else
ErrorF("stub poly_line\n");
return; return;
} }

View File

@ -44,14 +44,6 @@ glamor_fill_spans(DrawablePtr drawable,
int extentX1, extentX2, extentY1, extentY2; int extentX1, extentX2, extentY1, extentY2;
int fullX1, fullX2, fullY1; int fullX1, fullX2, fullY1;
int partX1, partX2; int partX1, partX2;
ScreenPtr screen = drawable->pScreen;
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable);
if (dest_pixmap != screen_pixmap) {
fbFillSpans(drawable, gc, n, points, widths, sorted);
return;
}
extents = REGION_EXTENTS(gc->pScreen, clip); extents = REGION_EXTENTS(gc->pScreen, clip);
extentX1 = extents->x1; extentX1 = extents->x1;

View File

@ -39,36 +39,33 @@ glamor_get_spans(DrawablePtr drawable,
int count, int count,
char *dst) char *dst)
{ {
ScreenPtr screen = drawable->pScreen;
PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
GLenum format, type;
int i;
if (screen_pixmap != pixmap) { switch (drawable->depth) {
case 24:
case 32:
format = GL_BGRA;
type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
default:
ErrorF("Unknown getspans depth %d\n", drawable->depth);
return;
}
if (!glamor_set_destination_pixmap(pixmap)) {
fbGetSpans(drawable, wmax, points, widths, count, dst); fbGetSpans(drawable, wmax, points, widths, count, dst);
return; return;
} else { }
GLenum format, type;
int i; for (i = 0; i < count; i++) {
switch (drawable->depth) { glReadPixels(points[i].x - pixmap->screen_x,
case 24: points[i].y - pixmap->screen_y,
case 32: widths[i],
format = GL_BGRA; 1,
type = GL_UNSIGNED_INT_8_8_8_8_REV; format, type,
break; dst);
default: dst += PixmapBytePad(widths[i], drawable->depth);
ErrorF("Unknown getspans depth %d\n", drawable->depth);
return;
}
if (!glamor_set_destination_pixmap(pixmap))
return;
for (i = 0; i < count; i++) {
glReadPixels(points[i].x - pixmap->screen_x,
points[i].y - pixmap->screen_y,
widths[i],
1,
format, type,
dst);
dst += PixmapBytePad(widths[i], drawable->depth);
}
} }
} }

View File

@ -50,13 +50,24 @@ typedef struct glamor_screen_private {
glamor_transform_uniforms solid_transform; glamor_transform_uniforms solid_transform;
} glamor_screen_private; } glamor_screen_private;
typedef struct glamor_pixmap_private {
GLuint tex;
GLuint fb;
} glamor_pixmap_private;
extern DevPrivateKey glamor_screen_private_key; extern DevPrivateKey glamor_screen_private_key;
extern DevPrivateKey glamor_pixmap_private_key;
static inline glamor_screen_private * static inline glamor_screen_private *
glamor_get_screen_private(ScreenPtr screen) glamor_get_screen_private(ScreenPtr screen)
{ {
return (glamor_screen_private *)dixLookupPrivate(&screen->devPrivates, return (glamor_screen_private *)dixLookupPrivate(&screen->devPrivates,
glamor_screen_private_key); glamor_screen_private_key);
} }
static inline glamor_pixmap_private *
glamor_get_pixmap_private(PixmapPtr pixmap)
{
return dixLookupPrivate(&pixmap->devPrivates, glamor_pixmap_private_key);
}
/* glamor.c */ /* glamor.c */
PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable); PixmapPtr glamor_get_drawable_pixmap(DrawablePtr drawable);