Commit 1495ba9e authored by Zhigang Gong's avatar Zhigang Gong Committed by Zhigang Gong

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.
parent 529c38a4
......@@ -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);
} 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);
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 {
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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment