xserver

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

glamor_core.c (8783B)


      1 /*
      2  * Copyright © 2001 Keith Packard
      3  * Copyright © 2008 Intel Corporation
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9  * and/or sell copies of the Software, and to permit persons to whom the
     10  * Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     22  * IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Eric Anholt <eric@anholt.net>
     26  *
     27  */
     28 
     29 /** @file glamor_core.c
     30  *
     31  * This file covers core X rendering in glamor.
     32  */
     33 
     34 #include <stdlib.h>
     35 
     36 #include "glamor_priv.h"
     37 
     38 Bool
     39 glamor_get_drawable_location(const DrawablePtr drawable)
     40 {
     41     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
     42     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
     43 
     44     if (pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED)
     45         return 'm';
     46     else
     47         return 'f';
     48 }
     49 
     50 GLint
     51 glamor_compile_glsl_prog(GLenum type, const char *source)
     52 {
     53     GLint ok;
     54     GLint prog;
     55 
     56     prog = glCreateShader(type);
     57     glShaderSource(prog, 1, (const GLchar **) &source, NULL);
     58     glCompileShader(prog);
     59     glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
     60     if (!ok) {
     61         GLchar *info;
     62         GLint size;
     63 
     64         glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
     65         info = malloc(size);
     66         if (info) {
     67             glGetShaderInfoLog(prog, size, NULL, info);
     68             ErrorF("Failed to compile %s: %s\n",
     69                    type == GL_FRAGMENT_SHADER ? "FS" : "VS", info);
     70             ErrorF("Program source:\n%s", source);
     71             free(info);
     72         }
     73         else
     74             ErrorF("Failed to get shader compilation info.\n");
     75         FatalError("GLSL compile failure\n");
     76     }
     77 
     78     return prog;
     79 }
     80 
     81 void
     82 glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...)
     83 {
     84     GLint ok;
     85     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     86 
     87     if (glamor_priv->has_khr_debug) {
     88         char *label;
     89         va_list va;
     90 
     91         va_start(va, format);
     92         XNFvasprintf(&label, format, va);
     93         glObjectLabel(GL_PROGRAM, prog, -1, label);
     94         free(label);
     95         va_end(va);
     96     }
     97 
     98     glLinkProgram(prog);
     99     glGetProgramiv(prog, GL_LINK_STATUS, &ok);
    100     if (!ok) {
    101         GLchar *info;
    102         GLint size;
    103 
    104         glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
    105         info = malloc(size);
    106 
    107         glGetProgramInfoLog(prog, size, NULL, info);
    108         ErrorF("Failed to link: %s\n", info);
    109         FatalError("GLSL link failure\n");
    110     }
    111 }
    112 
    113 
    114 static GCOps glamor_gc_ops = {
    115     .FillSpans = glamor_fill_spans,
    116     .SetSpans = glamor_set_spans,
    117     .PutImage = glamor_put_image,
    118     .CopyArea = glamor_copy_area,
    119     .CopyPlane = glamor_copy_plane,
    120     .PolyPoint = glamor_poly_point,
    121     .Polylines = glamor_poly_lines,
    122     .PolySegment = glamor_poly_segment,
    123     .PolyRectangle = miPolyRectangle,
    124     .PolyArc = miPolyArc,
    125     .FillPolygon = miFillPolygon,
    126     .PolyFillRect = glamor_poly_fill_rect,
    127     .PolyFillArc = miPolyFillArc,
    128     .PolyText8 = glamor_poly_text8,
    129     .PolyText16 = glamor_poly_text16,
    130     .ImageText8 = glamor_image_text8,
    131     .ImageText16 = glamor_image_text16,
    132     .ImageGlyphBlt = miImageGlyphBlt,
    133     .PolyGlyphBlt = glamor_poly_glyph_blt,
    134     .PushPixels = glamor_push_pixels,
    135 };
    136 
    137 /*
    138  * When the stipple is changed or drawn to, invalidate any
    139  * cached copy
    140  */
    141 static void
    142 glamor_invalidate_stipple(GCPtr gc)
    143 {
    144     glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    145 
    146     if (gc_priv->stipple) {
    147         if (gc_priv->stipple_damage)
    148             DamageUnregister(gc_priv->stipple_damage);
    149         glamor_destroy_pixmap(gc_priv->stipple);
    150         gc_priv->stipple = NULL;
    151     }
    152 }
    153 
    154 static void
    155 glamor_stipple_damage_report(DamagePtr damage, RegionPtr region,
    156                              void *closure)
    157 {
    158     GCPtr       gc = closure;
    159 
    160     glamor_invalidate_stipple(gc);
    161 }
    162 
    163 static void
    164 glamor_stipple_damage_destroy(DamagePtr damage, void *closure)
    165 {
    166     GCPtr               gc = closure;
    167     glamor_gc_private   *gc_priv = glamor_get_gc_private(gc);
    168 
    169     gc_priv->stipple_damage = NULL;
    170     glamor_invalidate_stipple(gc);
    171 }
    172 
    173 void
    174 glamor_track_stipple(GCPtr gc)
    175 {
    176     if (gc->stipple) {
    177         glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    178 
    179         if (!gc_priv->stipple_damage)
    180             gc_priv->stipple_damage = DamageCreate(glamor_stipple_damage_report,
    181                                                    glamor_stipple_damage_destroy,
    182                                                    DamageReportNonEmpty,
    183                                                    TRUE, gc->pScreen, gc);
    184         if (gc_priv->stipple_damage)
    185             DamageRegister(&gc->stipple->drawable, gc_priv->stipple_damage);
    186     }
    187 }
    188 
    189 /**
    190  * uxa_validate_gc() sets the ops to glamor's implementations, which may be
    191  * accelerated or may sync the card and fall back to fb.
    192  */
    193 void
    194 glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
    195 {
    196     /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
    197      * Preempt fbValidateGC by doing its work and masking the change out, so
    198      * that we can do the Prepare/finish_access.
    199      */
    200     if (changes & GCTile) {
    201         if (!gc->tileIsPixel) {
    202             glamor_pixmap_private *pixmap_priv =
    203                 glamor_get_pixmap_private(gc->tile.pixmap);
    204             if ((!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
    205                 && FbEvenTile(gc->tile.pixmap->drawable.width *
    206                               drawable->bitsPerPixel)) {
    207                 glamor_fallback
    208                     ("GC %p tile changed %p.\n", gc, gc->tile.pixmap);
    209                 if (glamor_prepare_access
    210                     (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW)) {
    211                     fbPadPixmap(gc->tile.pixmap);
    212                     glamor_finish_access(&gc->tile.pixmap->drawable);
    213                 }
    214             }
    215         }
    216         /* Mask out the GCTile change notification, now that we've done FB's
    217          * job for it.
    218          */
    219         changes &= ~GCTile;
    220     }
    221 
    222     if (changes & GCStipple)
    223         glamor_invalidate_stipple(gc);
    224 
    225     if (changes & GCStipple && gc->stipple) {
    226         /* We can't inline stipple handling like we do for GCTile because
    227          * it sets fbgc privates.
    228          */
    229         if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) {
    230             fbValidateGC(gc, changes, drawable);
    231             glamor_finish_access(&gc->stipple->drawable);
    232         }
    233     }
    234     else {
    235         fbValidateGC(gc, changes, drawable);
    236     }
    237 
    238     if (changes & GCDashList) {
    239         glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    240 
    241         if (gc_priv->dash) {
    242             glamor_destroy_pixmap(gc_priv->dash);
    243             gc_priv->dash = NULL;
    244         }
    245     }
    246 
    247     gc->ops = &glamor_gc_ops;
    248 }
    249 
    250 void
    251 glamor_destroy_gc(GCPtr gc)
    252 {
    253     glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    254 
    255     if (gc_priv->dash) {
    256         glamor_destroy_pixmap(gc_priv->dash);
    257         gc_priv->dash = NULL;
    258     }
    259     glamor_invalidate_stipple(gc);
    260     if (gc_priv->stipple_damage)
    261         DamageDestroy(gc_priv->stipple_damage);
    262     miDestroyGC(gc);
    263 }
    264 
    265 static GCFuncs glamor_gc_funcs = {
    266     glamor_validate_gc,
    267     miChangeGC,
    268     miCopyGC,
    269     glamor_destroy_gc,
    270     miChangeClip,
    271     miDestroyClip,
    272     miCopyClip
    273 };
    274 
    275 /**
    276  * exaCreateGC makes a new GC and hooks up its funcs handler, so that
    277  * exaValidateGC() will get called.
    278  */
    279 int
    280 glamor_create_gc(GCPtr gc)
    281 {
    282     glamor_gc_private *gc_priv = glamor_get_gc_private(gc);
    283 
    284     gc_priv->dash = NULL;
    285     gc_priv->stipple = NULL;
    286     if (!fbCreateGC(gc))
    287         return FALSE;
    288 
    289     gc->funcs = &glamor_gc_funcs;
    290 
    291     return TRUE;
    292 }
    293 
    294 RegionPtr
    295 glamor_bitmap_to_region(PixmapPtr pixmap)
    296 {
    297     RegionPtr ret;
    298 
    299     glamor_fallback("pixmap %p \n", pixmap);
    300     if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO))
    301         return NULL;
    302     ret = fbPixmapToRegion(pixmap);
    303     glamor_finish_access(&pixmap->drawable);
    304     return ret;
    305 }
    306