~gerchanovsky/xorg-server/xenial

« back to all changes in this revision

Viewing changes to glamor/glamor_prepare.c

  • Committer: Alex Gerchanovsky
  • Date: 2016-05-05 01:15:19 UTC
  • Revision ID: alex@ubuntu-20160505011519-ew0mn8tsloglbowd
InitialĀ 1.18.3-2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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_prepare.h"
 
25
#include "glamor_transfer.h"
 
26
 
 
27
/*
 
28
 * Make a pixmap ready to draw with fb by
 
29
 * creating a PBO large enough for the whole object
 
30
 * and downloading all of the FBOs into it.
 
31
 */
 
32
 
 
33
static Bool
 
34
glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box)
 
35
{
 
36
    ScreenPtr                   screen = pixmap->drawable.pScreen;
 
37
    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
 
38
    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
 
39
    int                         gl_access, gl_usage;
 
40
    RegionRec                   region;
 
41
 
 
42
    if (priv->type == GLAMOR_DRM_ONLY)
 
43
        return FALSE;
 
44
 
 
45
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
 
46
        return TRUE;
 
47
 
 
48
    glamor_make_current(glamor_priv);
 
49
 
 
50
    RegionInit(&region, box, 1);
 
51
 
 
52
    /* See if it's already mapped */
 
53
    if (pixmap->devPrivate.ptr) {
 
54
        /*
 
55
         * Someone else has mapped this pixmap;
 
56
         * we'll assume that it's directly mapped
 
57
         * by a lower level driver
 
58
         */
 
59
        if (!priv->prepared)
 
60
            return TRUE;
 
61
 
 
62
        /* In X, multiple Drawables can be stored in the same Pixmap (such as
 
63
         * each individual window in a non-composited screen pixmap, or the
 
64
         * reparented window contents inside the window-manager-decorated window
 
65
         * pixmap on a composited screen).
 
66
         *
 
67
         * As a result, when doing a series of mappings for a fallback, we may
 
68
         * need to add more boxes to the set of data we've downloaded, as we go.
 
69
         */
 
70
        RegionSubtract(&region, &region, &priv->prepare_region);
 
71
        if (!RegionNotEmpty(&region))
 
72
            return TRUE;
 
73
 
 
74
        if (access == GLAMOR_ACCESS_RW)
 
75
            FatalError("attempt to remap buffer as writable");
 
76
 
 
77
        if (priv->pbo) {
 
78
            glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->pbo);
 
79
            glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
 
80
            pixmap->devPrivate.ptr = NULL;
 
81
        }
 
82
    } else {
 
83
        RegionInit(&priv->prepare_region, box, 1);
 
84
 
 
85
        if (glamor_priv->has_rw_pbo) {
 
86
            if (priv->pbo == 0)
 
87
                glGenBuffers(1, &priv->pbo);
 
88
 
 
89
            gl_usage = GL_STREAM_READ;
 
90
 
 
91
            glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->pbo);
 
92
            glBufferData(GL_PIXEL_PACK_BUFFER,
 
93
                         pixmap->devKind * pixmap->drawable.height, NULL,
 
94
                         gl_usage);
 
95
        } else {
 
96
            pixmap->devPrivate.ptr = xallocarray(pixmap->devKind,
 
97
                                                 pixmap->drawable.height);
 
98
            if (!pixmap->devPrivate.ptr)
 
99
                return FALSE;
 
100
        }
 
101
        priv->map_access = access;
 
102
    }
 
103
 
 
104
    glamor_download_boxes(pixmap, RegionRects(&region), RegionNumRects(&region),
 
105
                          0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
 
106
 
 
107
    RegionUninit(&region);
 
108
 
 
109
    if (glamor_priv->has_rw_pbo) {
 
110
        if (priv->map_access == GLAMOR_ACCESS_RW)
 
111
            gl_access = GL_READ_WRITE;
 
112
        else
 
113
            gl_access = GL_READ_ONLY;
 
114
 
 
115
        pixmap->devPrivate.ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
 
116
        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
 
117
    }
 
118
 
 
119
    priv->prepared = TRUE;
 
120
    return TRUE;
 
121
}
 
122
 
 
123
/*
 
124
 * When we're done with the drawable, unmap the PBO, reupload
 
125
 * if we were writing to it and then unbind it to release the memory
 
126
 */
 
127
 
 
128
static void
 
129
glamor_fini_pixmap(PixmapPtr pixmap)
 
130
{
 
131
    ScreenPtr                   screen = pixmap->drawable.pScreen;
 
132
    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
 
133
    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
 
134
 
 
135
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
 
136
        return;
 
137
 
 
138
    if (!priv->prepared)
 
139
        return;
 
140
 
 
141
    if (glamor_priv->has_rw_pbo) {
 
142
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->pbo);
 
143
        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
 
144
        pixmap->devPrivate.ptr = NULL;
 
145
    }
 
146
 
 
147
    if (priv->map_access == GLAMOR_ACCESS_RW) {
 
148
        glamor_upload_boxes(pixmap,
 
149
                            RegionRects(&priv->prepare_region),
 
150
                            RegionNumRects(&priv->prepare_region),
 
151
                            0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
 
152
    }
 
153
 
 
154
    RegionUninit(&priv->prepare_region);
 
155
 
 
156
    if (glamor_priv->has_rw_pbo) {
 
157
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
158
        glDeleteBuffers(1, &priv->pbo);
 
159
        priv->pbo = 0;
 
160
    } else {
 
161
        free(pixmap->devPrivate.ptr);
 
162
        pixmap->devPrivate.ptr = NULL;
 
163
    }
 
164
 
 
165
    priv->prepared = FALSE;
 
166
}
 
167
 
 
168
Bool
 
169
glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
 
170
{
 
171
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
 
172
    BoxRec box;
 
173
    int off_x, off_y;
 
174
 
 
175
    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
 
176
 
 
177
    box.x1 = drawable->x + off_x;
 
178
    box.x2 = box.x1 + drawable->width;
 
179
    box.y1 = drawable->y + off_y;
 
180
    box.y2 = box.y1 + drawable->height;
 
181
    return glamor_prep_pixmap_box(pixmap, access, &box);
 
182
}
 
183
 
 
184
Bool
 
185
glamor_prepare_access_box(DrawablePtr drawable, glamor_access_t access,
 
186
                         int x, int y, int w, int h)
 
187
{
 
188
    PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
 
189
    BoxRec box;
 
190
    int off_x, off_y;
 
191
 
 
192
    glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
 
193
    box.x1 = drawable->x + x + off_x;
 
194
    box.x2 = box.x1 + w;
 
195
    box.y1 = drawable->y + y + off_y;
 
196
    box.y2 = box.y1 + h;
 
197
    return glamor_prep_pixmap_box(pixmap, access, &box);
 
198
}
 
199
 
 
200
void
 
201
glamor_finish_access(DrawablePtr drawable)
 
202
{
 
203
    glamor_fini_pixmap(glamor_get_drawable_pixmap(drawable));
 
204
}
 
205
 
 
206
/*
 
207
 * Make a picture ready to use with fb.
 
208
 */
 
209
 
 
210
Bool
 
211
glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
 
212
{
 
213
    if (!picture || !picture->pDrawable)
 
214
        return TRUE;
 
215
 
 
216
    return glamor_prepare_access(picture->pDrawable, access);
 
217
}
 
218
 
 
219
Bool
 
220
glamor_prepare_access_picture_box(PicturePtr picture, glamor_access_t access,
 
221
                        int x, int y, int w, int h)
 
222
{
 
223
    if (!picture || !picture->pDrawable)
 
224
        return TRUE;
 
225
 
 
226
    /* If a transform is set, we don't know what the bounds is on the
 
227
     * source, so just prepare the whole pixmap.  XXX: We could
 
228
     * potentially work out where in the source would be sampled based
 
229
     * on the transform, and we don't need do do this for destination
 
230
     * pixmaps at all.
 
231
     */
 
232
    if (picture->transform) {
 
233
        return glamor_prepare_access_box(picture->pDrawable, access,
 
234
                                         0, 0,
 
235
                                         picture->pDrawable->width,
 
236
                                         picture->pDrawable->height);
 
237
    } else {
 
238
        return glamor_prepare_access_box(picture->pDrawable, access,
 
239
                                         x, y, w, h);
 
240
    }
 
241
}
 
242
 
 
243
void
 
244
glamor_finish_access_picture(PicturePtr picture)
 
245
{
 
246
    if (!picture || !picture->pDrawable)
 
247
        return;
 
248
 
 
249
    glamor_finish_access(picture->pDrawable);
 
250
}
 
251
 
 
252
/*
 
253
 * Make a GC ready to use with fb. This just
 
254
 * means making sure the appropriate fill pixmap is
 
255
 * in CPU memory again
 
256
 */
 
257
 
 
258
Bool
 
259
glamor_prepare_access_gc(GCPtr gc)
 
260
{
 
261
    switch (gc->fillStyle) {
 
262
    case FillTiled:
 
263
        return glamor_prepare_access(&gc->tile.pixmap->drawable,
 
264
                                     GLAMOR_ACCESS_RO);
 
265
    case FillStippled:
 
266
    case FillOpaqueStippled:
 
267
        return glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO);
 
268
    }
 
269
    return TRUE;
 
270
}
 
271
 
 
272
/*
 
273
 * Free any temporary CPU pixmaps for the GC
 
274
 */
 
275
void
 
276
glamor_finish_access_gc(GCPtr gc)
 
277
{
 
278
    switch (gc->fillStyle) {
 
279
    case FillTiled:
 
280
        glamor_finish_access(&gc->tile.pixmap->drawable);
 
281
        break;
 
282
    case FillStippled:
 
283
    case FillOpaqueStippled:
 
284
        glamor_finish_access(&gc->stipple->drawable);
 
285
        break;
 
286
    }
 
287
}