diff options
Diffstat (limited to 'xorg-server/glamor/glamor_transform.c')
-rw-r--r-- | xorg-server/glamor/glamor_transform.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/xorg-server/glamor/glamor_transform.c b/xorg-server/glamor/glamor_transform.c new file mode 100644 index 000000000..d6ba56421 --- /dev/null +++ b/xorg-server/glamor/glamor_transform.c @@ -0,0 +1,215 @@ +/* + * Copyright © 2014 Keith Packard + * + * 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 appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + */ + +#include "glamor_priv.h" +#include "glamor_transform.h" + + +/* + * Set up rendering to target the specified drawable, computing an + * appropriate transform for the vertex shader to convert + * drawable-relative coordinates into pixmap-relative coordinates. If + * requested, the offset from pixmap origin coordinates back to window + * system coordinates will be returned in *p_off_x, *p_off_y so that + * clipping computations can be adjusted as appropriate + */ + +void +glamor_set_destination_drawable(DrawablePtr drawable, + int box_x, + int box_y, + Bool do_drawable_translate, + Bool center_offset, + GLint matrix_uniform_location, + int *p_off_x, + int *p_off_y) +{ + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); + int off_x, off_y; + BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_x, box_y); + int w = box->x2 - box->x1; + int h = box->y2 - box->y1; + float scale_x = 2.0f / (float) w; + float scale_y = 2.0f / (float) h; + float center_adjust = 0.0f; + + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + + off_x -= box->x1; + off_y -= box->y1; + + if (p_off_x) { + *p_off_x = off_x; + *p_off_y = off_y; + } + + /* A tricky computation to find the right value for the two linear functions + * that transform rendering coordinates to pixmap coordinates + * + * pixmap_x = render_x + drawable->x + off_x + * pixmap_y = render_y + drawable->y + off_y + * + * gl_x = pixmap_x * 2 / width - 1 + * gl_y = pixmap_y * 2 / height - 1 + * + * gl_x = (render_x + drawable->x + off_x) * 2 / width - 1 + * + * gl_x = (render_x) * 2 / width + (drawable->x + off_x) * 2 / width - 1 + * + * I'll think about yInverted later, when I have some way to test + */ + + if (do_drawable_translate) { + off_x += drawable->x; + off_y += drawable->y; + } + + /* + * To get GL_POINTS drawn in the right spot, we need to adjust the + * coordinates by 1/2 a pixel. + */ + if (center_offset) + center_adjust = 0.5f; + + glUniform4f(matrix_uniform_location, + scale_x, (off_x + center_adjust) * scale_x - 1.0f, + scale_y, (off_y + center_adjust) * scale_y - 1.0f); + + glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo_at(pixmap_priv, box_x, box_y), + 0, 0, w, h); +} + +/* + * Set up for solid rendering to the specified pixmap using alu, fg and planemask + * from the specified GC. Load the target color into the specified uniform + */ + +void +glamor_set_color(PixmapPtr pixmap, + CARD32 pixel, + GLint uniform) +{ + float color[4]; + + glamor_get_rgba_from_pixel(pixel, + &color[0], &color[1], &color[2], &color[3], + format_for_pixmap(pixmap)); + + glUniform4fv(uniform, 1, color); +} + +Bool +glamor_set_solid(PixmapPtr pixmap, + GCPtr gc, + Bool use_alu, + GLint uniform) +{ + CARD32 pixel; + int alu = use_alu ? gc->alu : GXcopy; + + if (!glamor_set_planemask(pixmap, gc->planemask)) + return FALSE; + + pixel = gc->fgPixel; + + if (!glamor_set_alu(pixmap->drawable.pScreen, alu)) { + switch (gc->alu) { + case GXclear: + pixel = 0; + break; + case GXcopyInverted: + pixel = ~pixel; + break; + case GXset: + pixel = ~0 & gc->planemask; + break; + default: + return FALSE; + } + } + glamor_set_color(pixmap, gc->fgPixel, uniform); + + return TRUE; +} + +Bool +glamor_set_texture(PixmapPtr pixmap, + PixmapPtr texture, + int off_x, + int off_y, + GLint offset_uniform, + GLint size_uniform) +{ + glamor_pixmap_private *texture_priv; + + texture_priv = glamor_get_pixmap_private(texture); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv)) + return FALSE; + + if (texture_priv->type == GLAMOR_TEXTURE_LARGE) + return FALSE; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture_priv->base.fbo->tex); + + glUniform2f(offset_uniform, off_x, off_y); + glUniform2f(size_uniform, texture->drawable.width, texture->drawable.height); + return TRUE; +} + +Bool +glamor_set_tiled(PixmapPtr pixmap, + GCPtr gc, + GLint offset_uniform, + GLint size_uniform) +{ + if (!glamor_set_alu(pixmap->drawable.pScreen, gc->alu)) + return FALSE; + + if (!glamor_set_planemask(pixmap, gc->planemask)) + return FALSE; + + return glamor_set_texture(pixmap, + gc->tile.pixmap, + -gc->patOrg.x, + -gc->patOrg.y, + offset_uniform, + size_uniform); +} + +Bool +glamor_set_stippled(PixmapPtr pixmap, + GCPtr gc, + GLint fg_uniform, + GLint offset_uniform, + GLint size_uniform) +{ + if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform)) + return FALSE; + + if (!glamor_set_texture(pixmap, gc->stipple, gc->patOrg.x, gc->patOrg.y, offset_uniform, size_uniform)) + return FALSE; + + return TRUE; +} |