glamor: Use buffer object as much as possible.

Change the row length of 1bit color depth pixmap to the actual stride.
The previous implementation use the width as its stride which is not
good. As it will waste 8 times of space and also bring some non-unify
code path. With this commit, we can merge those 1bit or other color
depth to almost one code path. And we will use pixel buffer object
as much as possible due to performance issue. By default, some mesa
hardware driver will fallback to software rasterization when use
glReadPixels on a non-buffer-object frame buffer. This change will
get about 4x times performance improvemention when we use y-inverted
glamor or the driver support hardware y-flipped blitting.
This commit is contained in:
Zhigang Gong 2011-05-22 17:51:27 +08:00 committed by Zhigang Gong
parent 529c38a460
commit 1495ba9e64

View File

@ -289,7 +289,7 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
{
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
unsigned int stride, read_stride, x, y;
unsigned int stride, row_length, x, y;
GLenum format, type;
uint8_t *data, *read;
glamor_screen_private *glamor_priv =
@ -307,15 +307,14 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
}
stride = pixmap->devKind;
read_stride = stride;
data = malloc(stride * pixmap->drawable.height);
row_length = (stride * 8) / pixmap->drawable.bitsPerPixel;
switch (drawable->depth) {
case 1:
format = GL_ALPHA;
type = GL_UNSIGNED_BYTE;
read_stride = pixmap->drawable.width;
row_length = stride;
break;
case 8:
format = GL_ALPHA;
@ -330,67 +329,47 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
break;
default:
ErrorF("Unknown prepareaccess depth %d\n", drawable->depth);
free(data);
return FALSE;
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pixmap_priv->fb);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
if (drawable->depth != 1) {
glPixelStorei(GL_PACK_ROW_LENGTH, read_stride * 8 /
pixmap->drawable.bitsPerPixel);
glPixelStorei(GL_PACK_ROW_LENGTH, row_length);
if (GLEW_MESA_pack_invert || glamor_priv->yInverted) {
if (!glamor_priv->yInverted)
glPixelStorei(GL_PACK_INVERT_MESA, 1);
glGenBuffersARB (1, &pixmap_priv->pbo);
glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo);
glBufferDataARB (GL_PIXEL_PACK_BUFFER_EXT,
stride * pixmap->drawable.height,
NULL, GL_DYNAMIC_DRAW_ARB);
glReadPixels (0, 0,
row_length, pixmap->drawable.height,
format, type, 0);
data = glMapBufferARB (GL_PIXEL_PACK_BUFFER_EXT, GL_READ_WRITE_ARB);
if (!glamor_priv->yInverted)
glPixelStorei(GL_PACK_INVERT_MESA, 0);
} else {
glPixelStorei(GL_PACK_ROW_LENGTH, read_stride);
}
if (GLEW_MESA_pack_invert && drawable->depth != 1) {
if (!glamor_priv->yInverted)
glPixelStorei(GL_PACK_INVERT_MESA, 1);
glReadPixels(0, 0,
pixmap->drawable.width, pixmap->drawable.height,
format, type, data);
if (!glamor_priv->yInverted)
glPixelStorei(GL_PACK_INVERT_MESA, 0);
} else {
glGenBuffersARB(1, &pixmap_priv->pbo);
data = malloc(stride * pixmap->drawable.height);
glGenBuffersARB(1, &pixmap_priv->pbo);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
read_stride * pixmap->drawable.height,
NULL, GL_STREAM_READ_ARB);
glReadPixels(0, 0,
pixmap->drawable.width, pixmap->drawable.height,
format, type, 0);
stride * pixmap->drawable.height,
NULL, GL_STREAM_READ_ARB);
glReadPixels (0, 0, row_length, pixmap->drawable.height,
format, type, 0);
read = glMapBufferARB(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY_ARB);
if (pixmap->drawable.depth == 1) {
for (y = 0; y < pixmap->drawable.height; y++) {
uint8_t *read_row;
uint8_t *write_row = data + y * stride;
if (glamor_priv->yInverted)
read_row = read + read_stride * y;
else
read_row = read +
read_stride * (pixmap->drawable.height - y - 1);
for (x = 0; x < pixmap->drawable.width; x++) {
int index = x / 8;
int bit = 1 << (x % 8);
if (read_row[x])
write_row[index] |= bit;
else
write_row[index] &= ~bit;
}
}
} else {
for (y = 0; y < pixmap->drawable.height; y++)
if (glamor_priv->yInverted)
memcpy(data + y * stride, read + y * stride, stride);
else
memcpy(data + y * stride,
read + (pixmap->drawable.height - y - 1) * stride, stride);
}
for (y = 0; y < pixmap->drawable.height; y++)
memcpy(data + y * stride,
read + (pixmap->drawable.height - y - 1) * stride, stride);
glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_EXT);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
glDeleteBuffersARB(1, &pixmap_priv->pbo);
@ -452,7 +431,7 @@ glamor_finish_access(DrawablePtr drawable)
glamor_get_screen_private(drawable->pScreen);
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
unsigned int stride;
unsigned int stride, row_length;
GLenum format, type;
static float vertices[4][2] = {{-1, -1},
{ 1, -1},
@ -489,10 +468,13 @@ glamor_finish_access(DrawablePtr drawable)
if (pixmap->devPrivate.ptr == NULL)
return;
stride = pixmap->devKind;
row_length = (stride * 8) / pixmap->drawable.bitsPerPixel;
switch (drawable->depth) {
case 1:
format = GL_COLOR_INDEX;
type = GL_BITMAP;
row_length = stride;
break;
case 8:
format = GL_ALPHA;
@ -510,7 +492,6 @@ glamor_finish_access(DrawablePtr drawable)
return;
}
stride = pixmap->devKind;
glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
@ -523,8 +504,7 @@ glamor_finish_access(DrawablePtr drawable)
glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8 /
pixmap->drawable.bitsPerPixel);
glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0);
@ -540,14 +520,21 @@ glamor_finish_access(DrawablePtr drawable)
glUseProgramObjectARB(glamor_priv->finish_access_prog);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisable(GL_TEXTURE_2D);
glUseProgramObjectARB(0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tex);
free(pixmap->devPrivate.ptr);
if (GLEW_MESA_pack_invert || glamor_priv->yInverted) {
glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, pixmap_priv->pbo);
glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_EXT);
glBindBufferARB (GL_PIXEL_PACK_BUFFER_EXT, 0);
glDeleteBuffersARB (1, &pixmap_priv->pbo);
pixmap_priv->pbo = 0;
} else
free(pixmap->devPrivate.ptr);
pixmap->devPrivate.ptr = NULL;
}