mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-04-07 18:10:39 +02:00
Merge branch 'glamor-accelerate-xy' into 'master'
WIP: Accelerate XY images in glamor See merge request xorg/xserver!417
This commit is contained in:
commit
e7cdcf9c44
2 changed files with 229 additions and 10 deletions
|
|
@ -29,8 +29,8 @@
|
|||
*/
|
||||
|
||||
static Bool
|
||||
glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
|
||||
int w, int h, int leftPad, int format, char *bits)
|
||||
glamor_put_image_zpixmap_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
|
||||
int w, int h, char *bits)
|
||||
{
|
||||
ScreenPtr screen = drawable->pScreen;
|
||||
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
|
||||
|
|
@ -52,12 +52,6 @@ glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
|
|||
if (!glamor_pm_is_solid(gc->depth, gc->planemask))
|
||||
goto bail;
|
||||
|
||||
if (format == XYPixmap && drawable->depth == 1 && leftPad == 0)
|
||||
format = ZPixmap;
|
||||
|
||||
if (format != ZPixmap)
|
||||
goto bail;
|
||||
|
||||
x += drawable->x;
|
||||
y += drawable->y;
|
||||
box.x1 = x;
|
||||
|
|
@ -84,6 +78,211 @@ bail:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static const char vs_vars_put_bitmap[] =
|
||||
"attribute vec4 primitive;\n"
|
||||
"attribute vec2 source;\n"
|
||||
"varying vec2 image_pos;\n";
|
||||
|
||||
static const char vs_exec_put_bitmap[] =
|
||||
" vec2 pos = primitive.zw * vec2(gl_VertexID&1, (gl_VertexID&2)>>1);\n"
|
||||
GLAMOR_POS(gl_Position, (primitive.xy + pos))
|
||||
" image_pos = source + pos;\n";
|
||||
|
||||
static const char fs_vars_put_bitmap[] =
|
||||
"varying vec2 image_pos;\n";
|
||||
|
||||
static Bool
|
||||
glamor_put_bitmap_use(DrawablePtr drawable, GCPtr gc, glamor_program *prog, void *arg)
|
||||
{
|
||||
if (!glamor_set_solid(drawable, gc, TRUE, prog->fg_uniform))
|
||||
return FALSE;
|
||||
glamor_set_color(drawable, gc->bgPixel, prog->bg_uniform);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const char fs_exec_put_bitmap[] =
|
||||
" ivec2 itile_texture = ivec2(image_pos);\n"
|
||||
" uint x = uint(itile_texture.x & 7);\n"
|
||||
" itile_texture.x >>= 3;\n"
|
||||
" uint texel = texelFetch(font, itile_texture, 0).x;\n"
|
||||
" uint bit = (texel >> x) & uint(1);\n"
|
||||
" if (bit == uint(0))\n"
|
||||
" gl_FragColor = bg;\n"
|
||||
" else\n"
|
||||
" gl_FragColor = fg;\n";
|
||||
|
||||
const glamor_facet glamor_facet_put_bitmap = {
|
||||
.name = "put_bitmap",
|
||||
.version = 130,
|
||||
.vs_vars = vs_vars_put_bitmap,
|
||||
.vs_exec = vs_exec_put_bitmap,
|
||||
.fs_vars = fs_vars_put_bitmap,
|
||||
.fs_exec = fs_exec_put_bitmap,
|
||||
.locations = glamor_program_location_fg | glamor_program_location_bg | glamor_program_location_font,
|
||||
.source_name = "source",
|
||||
.use = glamor_put_bitmap_use,
|
||||
};
|
||||
|
||||
/*
|
||||
* Use a program like the terminal emulator text program to fetch single
|
||||
* bits from the source image and expand them to full pixel values.
|
||||
*/
|
||||
static Bool
|
||||
glamor_put_image_xybitmap_gl(DrawablePtr drawable, GCPtr gc, int x, int y,
|
||||
int w, int h, int leftPad, char *bits)
|
||||
{
|
||||
ScreenPtr screen = drawable->pScreen;
|
||||
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
|
||||
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
|
||||
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
|
||||
uint32_t byte_stride = BitmapBytePad(w + leftPad);
|
||||
GLuint texture_id;
|
||||
glamor_program *prog;
|
||||
char *vbo_offset;
|
||||
GLshort *v;
|
||||
int box_index;
|
||||
int off_x, off_y;
|
||||
Bool ret = FALSE;
|
||||
|
||||
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
|
||||
return FALSE;
|
||||
|
||||
glamor_make_current(glamor_priv);
|
||||
|
||||
prog = &glamor_priv->put_bitmap_prog;
|
||||
|
||||
if (prog->failed)
|
||||
goto bail;
|
||||
|
||||
if (!prog->prog) {
|
||||
if (!glamor_build_program(screen, prog, &glamor_facet_put_bitmap, NULL, NULL, NULL))
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!glamor_use_program(&pixmap->drawable, gc, prog, NULL))
|
||||
goto bail;
|
||||
|
||||
glGenTextures(1, &texture_id);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glamor_priv->suppress_gl_out_of_memory_logging = true;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, byte_stride, h,
|
||||
0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, bits);
|
||||
glamor_priv->suppress_gl_out_of_memory_logging = false;
|
||||
if (glGetError() == GL_OUT_OF_MEMORY)
|
||||
goto bail;
|
||||
|
||||
glUniform1i(prog->font_uniform, 1);
|
||||
|
||||
/* Set up the vertex buffers for the font and destination */
|
||||
|
||||
v = glamor_get_vbo_space(drawable->pScreen, (6 * sizeof (GLshort)), &vbo_offset);
|
||||
|
||||
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 1);
|
||||
glVertexAttribPointer(GLAMOR_VERTEX_POS, 4, GL_SHORT, GL_FALSE,
|
||||
6 * sizeof (GLshort), vbo_offset);
|
||||
|
||||
glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 1);
|
||||
glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_SHORT, GL_FALSE,
|
||||
6 * sizeof (GLshort), vbo_offset + 4 * sizeof (GLshort));
|
||||
|
||||
v[0] = x;
|
||||
v[1] = y;
|
||||
v[2] = w;
|
||||
v[3] = h;
|
||||
v[4] = leftPad;
|
||||
v[5] = 0;
|
||||
|
||||
glamor_put_vbo_space(drawable->pScreen);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
glamor_pixmap_loop(pixmap_priv, box_index) {
|
||||
BoxPtr box = RegionRects(gc->pCompositeClip);
|
||||
int nbox = RegionNumRects(gc->pCompositeClip);
|
||||
|
||||
glamor_set_destination_drawable(drawable, box_index, TRUE, FALSE,
|
||||
prog->matrix_uniform,
|
||||
&off_x, &off_y);
|
||||
|
||||
/* Run over the clip list, drawing the glyphs
|
||||
* in each box
|
||||
*/
|
||||
|
||||
while (nbox--) {
|
||||
glScissor(box->x1 + off_x,
|
||||
box->y1 + off_y,
|
||||
box->x2 - box->x1,
|
||||
box->y2 - box->y1);
|
||||
box++;
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
|
||||
}
|
||||
}
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
|
||||
glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
|
||||
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
|
||||
|
||||
ret = TRUE;
|
||||
bail:
|
||||
glDeleteTextures(1, &texture_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a temporary in-memory pixmap, put the image there then copy
|
||||
* to the destination.
|
||||
*/
|
||||
|
||||
static Bool
|
||||
glamor_put_image_xy_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
|
||||
int w, int h, int leftPad, int format, char *bits)
|
||||
{
|
||||
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
|
||||
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
|
||||
ScreenPtr screen = drawable->pScreen;
|
||||
PixmapPtr temp_pixmap = NULL;
|
||||
DrawablePtr temp_drawable;
|
||||
GCPtr temp_gc;
|
||||
Bool ret = FALSE;
|
||||
ChangeGCVal gcv[3];
|
||||
|
||||
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
|
||||
return FALSE;
|
||||
|
||||
temp_pixmap = (*screen->CreatePixmap)(screen, w, h, drawable->depth, GLAMOR_CREATE_PIXMAP_CPU);
|
||||
if (!temp_pixmap)
|
||||
goto bail;
|
||||
temp_drawable = &temp_pixmap->drawable;
|
||||
temp_gc = GetScratchGC(temp_drawable->depth, screen);
|
||||
if (!temp_gc)
|
||||
goto bail_pixmap;
|
||||
|
||||
/* copy mode for the first plane to clear all of the other bits */
|
||||
gcv[0].val = GXcopy;
|
||||
gcv[1].val = gc->fgPixel;
|
||||
gcv[2].val = gc->bgPixel;
|
||||
ChangeGC(NullClient, temp_gc, GCFunction|GCForeground|GCBackground, gcv);
|
||||
ValidateGC(temp_drawable, temp_gc);
|
||||
(*temp_gc->ops->PutImage)(temp_drawable, temp_gc, depth, 0, 0, w, h, leftPad, format, bits);
|
||||
(*gc->ops->CopyArea)(&temp_pixmap->drawable, drawable, gc, 0, 0, w, h, x, y);
|
||||
ret = TRUE;
|
||||
|
||||
FreeScratchGC(temp_gc);
|
||||
bail_pixmap:
|
||||
(*screen->DestroyPixmap)(temp_pixmap);
|
||||
bail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
glamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
|
||||
int w, int h, int leftPad, int format, char *bits)
|
||||
|
|
@ -97,8 +296,25 @@ void
|
|||
glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
|
||||
int w, int h, int leftPad, int format, char *bits)
|
||||
{
|
||||
if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
|
||||
return;
|
||||
switch (format) {
|
||||
case ZPixmap:
|
||||
if (glamor_put_image_zpixmap_gl(drawable, gc, depth, x, y, w, h, bits))
|
||||
return;
|
||||
break;
|
||||
case XYPixmap:
|
||||
if (glamor_put_image_xy_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
|
||||
return;
|
||||
break;
|
||||
case XYBitmap:
|
||||
if (w * h >= 100 * 100) {
|
||||
if (glamor_put_image_xybitmap_gl(drawable, gc, x, y, w, h, leftPad, bits))
|
||||
return;
|
||||
} else {
|
||||
if (glamor_put_image_xy_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -280,6 +280,9 @@ typedef struct glamor_screen_private {
|
|||
glamor_program copy_area_prog;
|
||||
glamor_program copy_plane_prog;
|
||||
|
||||
/* glamor image shaders */
|
||||
glamor_program put_bitmap_prog;
|
||||
|
||||
/* glamor line shader */
|
||||
glamor_program_fill poly_line_program;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue