glamor_core.c 8.58 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
/*
 * Copyright © 2001 Keith Packard
 * Copyright © 2008 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 * Authors:
 *    Eric Anholt <eric@anholt.net>
 *
 */

/** @file glamor_core.c
 *
 * This file covers core X rendering in glamor.
 */

#include <stdlib.h>

#include "glamor_priv.h"

38
Bool
39 40
glamor_get_drawable_location(const DrawablePtr drawable)
{
Eric Anholt's avatar
Eric Anholt committed
41 42
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
43

44
    if (pixmap_priv->gl_fbo == GLAMOR_FBO_UNATTACHED)
Eric Anholt's avatar
Eric Anholt committed
45 46 47
        return 'm';
    else
        return 'f';
48 49
}

50
GLint
51
glamor_compile_glsl_prog(GLenum type, const char *source)
52
{
Eric Anholt's avatar
Eric Anholt committed
53 54 55
    GLint ok;
    GLint prog;

56 57 58 59
    prog = glCreateShader(type);
    glShaderSource(prog, 1, (const GLchar **) &source, NULL);
    glCompileShader(prog);
    glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
Eric Anholt's avatar
Eric Anholt committed
60 61 62 63
    if (!ok) {
        GLchar *info;
        GLint size;

64
        glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
Eric Anholt's avatar
Eric Anholt committed
65 66
        info = malloc(size);
        if (info) {
67
            glGetShaderInfoLog(prog, size, NULL, info);
Eric Anholt's avatar
Eric Anholt committed
68 69 70 71 72 73 74 75 76 77 78
            ErrorF("Failed to compile %s: %s\n",
                   type == GL_FRAGMENT_SHADER ? "FS" : "VS", info);
            ErrorF("Program source:\n%s", source);
            free(info);
        }
        else
            ErrorF("Failed to get shader compilation info.\n");
        FatalError("GLSL compile failure\n");
    }

    return prog;
79 80 81
}

void
82
glamor_link_glsl_prog(ScreenPtr screen, GLint prog, const char *format, ...)
83
{
Eric Anholt's avatar
Eric Anholt committed
84
    GLint ok;
85
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
Zhigang Gong's avatar
Zhigang Gong committed
86

87 88 89 90 91 92 93 94 95 96 97
    if (glamor_priv->has_khr_debug) {
        char *label;
        va_list va;

        va_start(va, format);
        XNFvasprintf(&label, format, va);
        glObjectLabel(GL_PROGRAM, prog, -1, label);
        free(label);
        va_end(va);
    }

98 99
    glLinkProgram(prog);
    glGetProgramiv(prog, GL_LINK_STATUS, &ok);
Eric Anholt's avatar
Eric Anholt committed
100 101 102
    if (!ok) {
        GLchar *info;
        GLint size;
Zhigang Gong's avatar
Zhigang Gong committed
103

104
        glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
Eric Anholt's avatar
Eric Anholt committed
105
        info = malloc(size);
Zhigang Gong's avatar
Zhigang Gong committed
106

107
        glGetProgramInfoLog(prog, size, NULL, info);
Eric Anholt's avatar
Eric Anholt committed
108 109 110
        ErrorF("Failed to link: %s\n", info);
        FatalError("GLSL link failure\n");
    }
111 112
}

113

114
static GCOps glamor_gc_ops = {
Eric Anholt's avatar
Eric Anholt committed
115 116 117 118 119 120 121 122 123 124 125 126 127
    .FillSpans = glamor_fill_spans,
    .SetSpans = glamor_set_spans,
    .PutImage = glamor_put_image,
    .CopyArea = glamor_copy_area,
    .CopyPlane = glamor_copy_plane,
    .PolyPoint = glamor_poly_point,
    .Polylines = glamor_poly_lines,
    .PolySegment = glamor_poly_segment,
    .PolyRectangle = miPolyRectangle,
    .PolyArc = miPolyArc,
    .FillPolygon = miFillPolygon,
    .PolyFillRect = glamor_poly_fill_rect,
    .PolyFillArc = miPolyFillArc,
128 129 130 131
    .PolyText8 = glamor_poly_text8,
    .PolyText16 = glamor_poly_text16,
    .ImageText8 = glamor_image_text8,
    .ImageText16 = glamor_image_text16,
132 133 134
    .ImageGlyphBlt = miImageGlyphBlt,
    .PolyGlyphBlt = glamor_poly_glyph_blt,
    .PushPixels = glamor_push_pixels,
135 136
};

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
/*
 * When the stipple is changed or drawn to, invalidate any
 * cached copy
 */
static void
glamor_invalidate_stipple(GCPtr gc)
{
    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);

    if (gc_priv->stipple) {
        if (gc_priv->stipple_damage)
            DamageUnregister(gc_priv->stipple_damage);
        glamor_destroy_pixmap(gc_priv->stipple);
        gc_priv->stipple = NULL;
    }
}

static void
glamor_stipple_damage_report(DamagePtr damage, RegionPtr region,
                             void *closure)
{
    GCPtr       gc = closure;

    glamor_invalidate_stipple(gc);
}

static void
glamor_stipple_damage_destroy(DamagePtr damage, void *closure)
{
    GCPtr               gc = closure;
    glamor_gc_private   *gc_priv = glamor_get_gc_private(gc);

    gc_priv->stipple_damage = NULL;
    glamor_invalidate_stipple(gc);
}

void
glamor_track_stipple(GCPtr gc)
{
    if (gc->stipple) {
        glamor_gc_private *gc_priv = glamor_get_gc_private(gc);

        if (!gc_priv->stipple_damage)
            gc_priv->stipple_damage = DamageCreate(glamor_stipple_damage_report,
                                                   glamor_stipple_damage_destroy,
                                                   DamageReportNonEmpty,
                                                   TRUE, gc->pScreen, gc);
        if (gc_priv->stipple_damage)
            DamageRegister(&gc->stipple->drawable, gc_priv->stipple_damage);
    }
}

189
/**
190
 * uxa_validate_gc() sets the ops to glamor's implementations, which may be
191 192
 * accelerated or may sync the card and fall back to fb.
 */
193
void
194 195
glamor_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
{
Eric Anholt's avatar
Eric Anholt committed
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
    /* fbValidateGC will do direct access to pixmaps if the tiling has changed.
     * Preempt fbValidateGC by doing its work and masking the change out, so
     * that we can do the Prepare/finish_access.
     */
    if (changes & GCTile) {
        if (!gc->tileIsPixel) {
            glamor_pixmap_private *pixmap_priv =
                glamor_get_pixmap_private(gc->tile.pixmap);
            if ((!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
                && FbEvenTile(gc->tile.pixmap->drawable.width *
                              drawable->bitsPerPixel)) {
                glamor_fallback
                    ("GC %p tile changed %p.\n", gc, gc->tile.pixmap);
                if (glamor_prepare_access
                    (&gc->tile.pixmap->drawable, GLAMOR_ACCESS_RW)) {
                    fbPadPixmap(gc->tile.pixmap);
212
                    glamor_finish_access(&gc->tile.pixmap->drawable);
Eric Anholt's avatar
Eric Anholt committed
213 214 215 216 217 218 219 220 221
                }
            }
        }
        /* Mask out the GCTile change notification, now that we've done FB's
         * job for it.
         */
        changes &= ~GCTile;
    }

222 223 224
    if (changes & GCStipple)
        glamor_invalidate_stipple(gc);

Eric Anholt's avatar
Eric Anholt committed
225 226 227 228 229 230
    if (changes & GCStipple && gc->stipple) {
        /* We can't inline stipple handling like we do for GCTile because
         * it sets fbgc privates.
         */
        if (glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RW)) {
            fbValidateGC(gc, changes, drawable);
231
            glamor_finish_access(&gc->stipple->drawable);
Eric Anholt's avatar
Eric Anholt committed
232 233 234 235 236 237
        }
    }
    else {
        fbValidateGC(gc, changes, drawable);
    }

238 239 240 241 242 243 244 245 246
    if (changes & GCDashList) {
        glamor_gc_private *gc_priv = glamor_get_gc_private(gc);

        if (gc_priv->dash) {
            glamor_destroy_pixmap(gc_priv->dash);
            gc_priv->dash = NULL;
        }
    }

Eric Anholt's avatar
Eric Anholt committed
247
    gc->ops = &glamor_gc_ops;
248 249
}

250 251 252 253 254 255 256 257 258
void
glamor_destroy_gc(GCPtr gc)
{
    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);

    if (gc_priv->dash) {
        glamor_destroy_pixmap(gc_priv->dash);
        gc_priv->dash = NULL;
    }
259 260 261
    glamor_invalidate_stipple(gc);
    if (gc_priv->stipple_damage)
        DamageDestroy(gc_priv->stipple_damage);
262 263 264
    miDestroyGC(gc);
}

265
static GCFuncs glamor_gc_funcs = {
Eric Anholt's avatar
Eric Anholt committed
266 267 268
    glamor_validate_gc,
    miChangeGC,
    miCopyGC,
269
    glamor_destroy_gc,
Eric Anholt's avatar
Eric Anholt committed
270 271 272
    miChangeClip,
    miDestroyClip,
    miCopyClip
273 274 275 276 277 278 279 280 281
};

/**
 * exaCreateGC makes a new GC and hooks up its funcs handler, so that
 * exaValidateGC() will get called.
 */
int
glamor_create_gc(GCPtr gc)
{
282 283 284
    glamor_gc_private *gc_priv = glamor_get_gc_private(gc);

    gc_priv->dash = NULL;
285
    gc_priv->stipple = NULL;
Eric Anholt's avatar
Eric Anholt committed
286 287
    if (!fbCreateGC(gc))
        return FALSE;
288

Eric Anholt's avatar
Eric Anholt committed
289
    gc->funcs = &glamor_gc_funcs;
290

Eric Anholt's avatar
Eric Anholt committed
291
    return TRUE;
292
}
293 294 295 296

RegionPtr
glamor_bitmap_to_region(PixmapPtr pixmap)
{
Eric Anholt's avatar
Eric Anholt committed
297 298 299 300 301 302
    RegionPtr ret;

    glamor_fallback("pixmap %p \n", pixmap);
    if (!glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RO))
        return NULL;
    ret = fbPixmapToRegion(pixmap);
303
    glamor_finish_access(&pixmap->drawable);
Eric Anholt's avatar
Eric Anholt committed
304
    return ret;
305
}
306