xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

glamor_transform.c (9674B)


      1 /*
      2  * Copyright © 2014 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 #include "glamor_priv.h"
     24 #include "glamor_transform.h"
     25 
     26 
     27 /*
     28  * Set up rendering to target the specified drawable, computing an
     29  * appropriate transform for the vertex shader to convert
     30  * drawable-relative coordinates into pixmap-relative coordinates. If
     31  * requested, the offset from pixmap origin coordinates back to window
     32  * system coordinates will be returned in *p_off_x, *p_off_y so that
     33  * clipping computations can be adjusted as appropriate
     34  */
     35 
     36 Bool
     37 glamor_set_destination_drawable(DrawablePtr     drawable,
     38                                 int             box_index,
     39                                 Bool            do_drawable_translate,
     40                                 Bool            center_offset,
     41                                 GLint           matrix_uniform_location,
     42                                 int             *p_off_x,
     43                                 int             *p_off_y)
     44 {
     45     ScreenPtr screen = drawable->pScreen;
     46     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     47     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
     48     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
     49     int off_x, off_y;
     50     BoxPtr box = glamor_pixmap_box_at(pixmap_priv, box_index);
     51     int w = box->x2 - box->x1;
     52     int h = box->y2 - box->y1;
     53     float scale_x = 2.0f / (float) w;
     54     float scale_y = 2.0f / (float) h;
     55     float center_adjust = 0.0f;
     56     glamor_pixmap_fbo *pixmap_fbo;
     57 
     58     pixmap_fbo = glamor_pixmap_fbo_at(pixmap_priv, box_index);
     59     if (!pixmap_fbo)
     60         return FALSE;
     61 
     62     glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
     63 
     64     off_x -= box->x1;
     65     off_y -= box->y1;
     66 
     67     if (p_off_x) {
     68         *p_off_x = off_x;
     69         *p_off_y = off_y;
     70     }
     71 
     72     /* A tricky computation to find the right value for the two linear functions
     73      * that transform rendering coordinates to pixmap coordinates
     74      *
     75      *  pixmap_x = render_x + drawable->x + off_x
     76      *  pixmap_y = render_y + drawable->y + off_y
     77      *
     78      *  gl_x = pixmap_x * 2 / width - 1
     79      *  gl_y = pixmap_y * 2 / height - 1
     80      *
     81      *  gl_x = (render_x + drawable->x + off_x) * 2 / width - 1
     82      *
     83      *  gl_x = (render_x) * 2 / width + (drawable->x + off_x) * 2 / width - 1
     84      */
     85 
     86     if (do_drawable_translate) {
     87         off_x += drawable->x;
     88         off_y += drawable->y;
     89     }
     90 
     91     /*
     92      * To get GL_POINTS drawn in the right spot, we need to adjust the
     93      * coordinates by 1/2 a pixel.
     94      */
     95     if (center_offset)
     96         center_adjust = 0.5f;
     97 
     98     glUniform4f(matrix_uniform_location,
     99                 scale_x, (off_x + center_adjust) * scale_x - 1.0f,
    100                 scale_y, (off_y + center_adjust) * scale_y - 1.0f);
    101 
    102     glamor_set_destination_pixmap_fbo(glamor_priv, pixmap_fbo,
    103                                       0, 0, w, h);
    104 
    105     return TRUE;
    106 }
    107 
    108 /*
    109  * Set up for solid rendering to the specified pixmap using alu, fg and planemask
    110  * from the specified GC. Load the target color into the specified uniform
    111  */
    112 
    113 void
    114 glamor_set_color_depth(ScreenPtr      pScreen,
    115                        int            depth,
    116                        CARD32         pixel,
    117                        GLint          uniform)
    118 {
    119     glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
    120     float       color[4];
    121 
    122     glamor_get_rgba_from_pixel(pixel,
    123                                &color[0], &color[1], &color[2], &color[3],
    124                                glamor_priv->formats[depth].render_format);
    125 
    126     if ((depth <= 8) && glamor_priv->formats[8].format == GL_RED)
    127       color[0] = color[3];
    128 
    129     glUniform4fv(uniform, 1, color);
    130 }
    131 
    132 Bool
    133 glamor_set_solid(PixmapPtr      pixmap,
    134                  GCPtr          gc,
    135                  Bool           use_alu,
    136                  GLint          uniform)
    137 {
    138     CARD32      pixel;
    139     int         alu = use_alu ? gc->alu : GXcopy;
    140 
    141     if (!glamor_set_planemask(gc->depth, gc->planemask))
    142         return FALSE;
    143 
    144     pixel = gc->fgPixel;
    145 
    146     if (!glamor_set_alu(pixmap->drawable.pScreen, alu)) {
    147         switch (gc->alu) {
    148         case GXclear:
    149             pixel = 0;
    150             break;
    151         case GXcopyInverted:
    152             pixel = ~pixel;
    153             break;
    154         case GXset:
    155             pixel = ~0 & gc->planemask;
    156             break;
    157         default:
    158             return FALSE;
    159         }
    160     }
    161     glamor_set_color(pixmap, pixel, uniform);
    162 
    163     return TRUE;
    164 }
    165 
    166 Bool
    167 glamor_set_texture_pixmap(PixmapPtr texture, Bool destination_red)
    168 {
    169     glamor_pixmap_private *texture_priv;
    170 
    171     texture_priv = glamor_get_pixmap_private(texture);
    172 
    173     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(texture_priv))
    174         return FALSE;
    175 
    176     if (glamor_pixmap_priv_is_large(texture_priv))
    177         return FALSE;
    178 
    179     glamor_bind_texture(glamor_get_screen_private(texture->drawable.pScreen),
    180                         GL_TEXTURE0,
    181                         texture_priv->fbo, destination_red);
    182 
    183     /* we're not setting the sampler uniform here as we always use
    184      * GL_TEXTURE0, and the default value for uniforms is zero. So,
    185      * save a bit of CPU time by taking advantage of that.
    186      */
    187     return TRUE;
    188 }
    189 
    190 Bool
    191 glamor_set_texture(PixmapPtr    texture,
    192                    Bool         destination_red,
    193                    int          off_x,
    194                    int          off_y,
    195                    GLint        offset_uniform,
    196                    GLint        size_inv_uniform)
    197 {
    198     if (!glamor_set_texture_pixmap(texture, destination_red))
    199         return FALSE;
    200 
    201     glUniform2f(offset_uniform, off_x, off_y);
    202     glUniform2f(size_inv_uniform, 1.0f/texture->drawable.width, 1.0f/texture->drawable.height);
    203     return TRUE;
    204 }
    205 
    206 Bool
    207 glamor_set_tiled(PixmapPtr      pixmap,
    208                  GCPtr          gc,
    209                  GLint          offset_uniform,
    210                  GLint          size_inv_uniform)
    211 {
    212     if (!glamor_set_alu(pixmap->drawable.pScreen, gc->alu))
    213         return FALSE;
    214 
    215     if (!glamor_set_planemask(gc->depth, gc->planemask))
    216         return FALSE;
    217 
    218     return glamor_set_texture(gc->tile.pixmap,
    219                               TRUE,
    220                               -gc->patOrg.x,
    221                               -gc->patOrg.y,
    222                               offset_uniform,
    223                               size_inv_uniform);
    224 }
    225 
    226 static PixmapPtr
    227 glamor_get_stipple_pixmap(GCPtr gc)
    228 {
    229     glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    230     ScreenPtr   screen = gc->pScreen;
    231     PixmapPtr   bitmap;
    232     PixmapPtr   pixmap;
    233     GCPtr       scratch_gc;
    234     ChangeGCVal changes[2];
    235 
    236     if (gc_priv->stipple)
    237         return gc_priv->stipple;
    238 
    239     bitmap = gc->stipple;
    240     if (!bitmap)
    241         goto bail;
    242 
    243     pixmap = glamor_create_pixmap(screen,
    244                                   bitmap->drawable.width,
    245                                   bitmap->drawable.height,
    246                                   8, GLAMOR_CREATE_NO_LARGE);
    247     if (!pixmap)
    248         goto bail;
    249 
    250     scratch_gc = GetScratchGC(8, screen);
    251     if (!scratch_gc)
    252         goto bail_pixmap;
    253 
    254     changes[0].val = 0xff;
    255     changes[1].val = 0x00;
    256     if (ChangeGC(NullClient, scratch_gc,
    257                  GCForeground|GCBackground, changes) != Success)
    258         goto bail_gc;
    259     ValidateGC(&pixmap->drawable, scratch_gc);
    260 
    261     (*scratch_gc->ops->CopyPlane)(&bitmap->drawable,
    262                                   &pixmap->drawable,
    263                                   scratch_gc,
    264                                   0, 0,
    265                                   bitmap->drawable.width,
    266                                   bitmap->drawable.height,
    267                                   0, 0, 0x1);
    268 
    269     FreeScratchGC(scratch_gc);
    270     gc_priv->stipple = pixmap;
    271 
    272     glamor_track_stipple(gc);
    273 
    274     return pixmap;
    275 
    276 bail_gc:
    277     FreeScratchGC(scratch_gc);
    278 bail_pixmap:
    279     glamor_destroy_pixmap(pixmap);
    280 bail:
    281     return NULL;
    282 }
    283 
    284 Bool
    285 glamor_set_stippled(PixmapPtr      pixmap,
    286                     GCPtr          gc,
    287                     GLint          fg_uniform,
    288                     GLint          offset_uniform,
    289                     GLint          size_uniform)
    290 {
    291     PixmapPtr   stipple;
    292 
    293     stipple = glamor_get_stipple_pixmap(gc);
    294     if (!stipple)
    295         return FALSE;
    296 
    297     if (!glamor_set_solid(pixmap, gc, TRUE, fg_uniform))
    298         return FALSE;
    299 
    300     return glamor_set_texture(stipple,
    301                               FALSE,
    302                               -gc->patOrg.x,
    303                               -gc->patOrg.y,
    304                               offset_uniform,
    305                               size_uniform);
    306 }