~gerchanovsky/xorg-server/trusty

« back to all changes in this revision

Viewing changes to glamor/glamor_transfer.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2016-01-13 00:01:28 UTC
  • Revision ID: package-import@ubuntu.com-20160113000128-oc1wb1mr1zfjqlm5
Tags: upstream-1.17.2
ImportĀ upstreamĀ versionĀ 1.17.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_transfer.h"
 
25
 
 
26
/* XXX a kludge for now */
 
27
void
 
28
glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type)
 
29
{
 
30
    switch (pixmap->drawable.depth) {
 
31
    case 24:
 
32
    case 32:
 
33
        *format = GL_BGRA;
 
34
        *type = GL_UNSIGNED_INT_8_8_8_8_REV;
 
35
        break;
 
36
    case 16:
 
37
        *format = GL_RGB;
 
38
        *type = GL_UNSIGNED_SHORT_5_6_5;
 
39
        break;
 
40
    case 15:
 
41
        *format = GL_BGRA;
 
42
        *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
 
43
        break;
 
44
    case 8:
 
45
        *format = GL_ALPHA;
 
46
        *type = GL_UNSIGNED_BYTE;
 
47
        break;
 
48
    default:
 
49
        FatalError("Invalid pixmap depth %d\n", pixmap->drawable.depth);
 
50
        break;
 
51
    }
 
52
}
 
53
 
 
54
/*
 
55
 * Write a region of bits into a pixmap
 
56
 */
 
57
void
 
58
glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
 
59
                    int dx_src, int dy_src,
 
60
                    int dx_dst, int dy_dst,
 
61
                    uint8_t *bits, uint32_t byte_stride)
 
62
{
 
63
    ScreenPtr                   screen = pixmap->drawable.pScreen;
 
64
    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
 
65
    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
 
66
    int                         box_x, box_y;
 
67
    int                         bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
 
68
    GLenum                      type;
 
69
    GLenum                      format;
 
70
 
 
71
    glamor_format_for_pixmap(pixmap, &format, &type);
 
72
 
 
73
    glamor_make_current(glamor_priv);
 
74
 
 
75
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
76
 
 
77
    if (glamor_priv->has_unpack_subimage)
 
78
        glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
 
79
 
 
80
    glamor_pixmap_loop(priv, box_x, box_y) {
 
81
        BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
 
82
        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
 
83
        BoxPtr                  boxes = in_boxes;
 
84
        int                     nbox = in_nbox;
 
85
 
 
86
        glActiveTexture(GL_TEXTURE0);
 
87
        glBindTexture(GL_TEXTURE_2D, fbo->tex);
 
88
 
 
89
        while (nbox--) {
 
90
 
 
91
            /* compute drawable coordinates */
 
92
            int x1 = MAX(boxes->x1 + dx_dst, box->x1);
 
93
            int x2 = MIN(boxes->x2 + dx_dst, box->x2);
 
94
            int y1 = MAX(boxes->y1 + dy_dst, box->y1);
 
95
            int y2 = MIN(boxes->y2 + dy_dst, box->y2);
 
96
 
 
97
            size_t ofs = (y1 - dy_dst + dy_src) * byte_stride;
 
98
            ofs += (x1 - dx_dst + dx_src) * bytes_per_pixel;
 
99
 
 
100
            boxes++;
 
101
 
 
102
            if (x2 <= x1 || y2 <= y1)
 
103
                continue;
 
104
 
 
105
            if (glamor_priv->has_unpack_subimage ||
 
106
                x2 - x1 == byte_stride / bytes_per_pixel) {
 
107
                glTexSubImage2D(GL_TEXTURE_2D, 0,
 
108
                                x1 - box->x1, y1 - box->y1,
 
109
                                x2 - x1, y2 - y1,
 
110
                                format, type,
 
111
                                bits + ofs);
 
112
            } else {
 
113
                for (; y1 < y2; y1++, ofs += byte_stride)
 
114
                    glTexSubImage2D(GL_TEXTURE_2D, 0,
 
115
                                    x1 - box->x1, y1 - box->y1,
 
116
                                    x2 - x1, 1,
 
117
                                    format, type,
 
118
                                    bits + ofs);
 
119
            }
 
120
        }
 
121
    }
 
122
 
 
123
    if (glamor_priv->has_unpack_subimage)
 
124
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 
125
}
 
126
 
 
127
/*
 
128
 * Upload a region of data
 
129
 */
 
130
 
 
131
void
 
132
glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
 
133
                     int region_x, int region_y,
 
134
                     uint8_t *bits, uint32_t byte_stride)
 
135
{
 
136
    glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
 
137
                        -region_x, -region_y,
 
138
                        0, 0,
 
139
                        bits, byte_stride);
 
140
}
 
141
 
 
142
/*
 
143
 * Take the data in the pixmap and stuff it back into the FBO
 
144
 */
 
145
void
 
146
glamor_upload_pixmap(PixmapPtr pixmap)
 
147
{
 
148
    BoxRec box;
 
149
 
 
150
    box.x1 = 0;
 
151
    box.x2 = pixmap->drawable.width;
 
152
    box.y1 = 0;
 
153
    box.y2 = pixmap->drawable.height;
 
154
    glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
 
155
                        pixmap->devPrivate.ptr, pixmap->devKind);
 
156
}
 
157
 
 
158
/*
 
159
 * Read stuff from the pixmap FBOs and write to memory
 
160
 */
 
161
void
 
162
glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
 
163
                      int dx_src, int dy_src,
 
164
                      int dx_dst, int dy_dst,
 
165
                      uint8_t *bits, uint32_t byte_stride)
 
166
{
 
167
    ScreenPtr screen = pixmap->drawable.pScreen;
 
168
    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
169
    glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
 
170
    int box_x, box_y;
 
171
    int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
 
172
    GLenum type;
 
173
    GLenum format;
 
174
 
 
175
    glamor_format_for_pixmap(pixmap, &format, &type);
 
176
 
 
177
    glamor_make_current(glamor_priv);
 
178
 
 
179
    glPixelStorei(GL_PACK_ALIGNMENT, 4);
 
180
    if (glamor_priv->has_pack_subimage)
 
181
        glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
 
182
 
 
183
    glamor_pixmap_loop(priv, box_x, box_y) {
 
184
        BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
 
185
        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
 
186
        BoxPtr                  boxes = in_boxes;
 
187
        int                     nbox = in_nbox;
 
188
 
 
189
        glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
 
190
 
 
191
        while (nbox--) {
 
192
 
 
193
            /* compute drawable coordinates */
 
194
            int                     x1 = MAX(boxes->x1 + dx_src, box->x1);
 
195
            int                     x2 = MIN(boxes->x2 + dx_src, box->x2);
 
196
            int                     y1 = MAX(boxes->y1 + dy_src, box->y1);
 
197
            int                     y2 = MIN(boxes->y2 + dy_src, box->y2);
 
198
            size_t ofs = (y1 - dy_src + dy_dst) * byte_stride;
 
199
            ofs += (x1 - dx_src + dx_dst) * bytes_per_pixel;
 
200
 
 
201
            boxes++;
 
202
 
 
203
            if (x2 <= x1 || y2 <= y1)
 
204
                continue;
 
205
 
 
206
            if (glamor_priv->has_pack_subimage ||
 
207
                x2 - x1 == byte_stride / bytes_per_pixel) {
 
208
                glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits + ofs);
 
209
            } else {
 
210
                for (; y1 < y2; y1++, ofs += byte_stride)
 
211
                    glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs);
 
212
            }
 
213
        }
 
214
    }
 
215
    if (glamor_priv->has_pack_subimage)
 
216
        glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 
217
}
 
218
 
 
219
/*
 
220
 * Read data from the pixmap FBO
 
221
 */
 
222
void
 
223
glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits)
 
224
{
 
225
    BoxRec      box;
 
226
 
 
227
    box.x1 = x;
 
228
    box.x2 = x + w;
 
229
    box.y1 = y;
 
230
    box.y2 = y + h;
 
231
 
 
232
    glamor_download_boxes(pixmap, &box, 1, 0, 0, -x, -y,
 
233
                          bits, PixmapBytePad(w, pixmap->drawable.depth));
 
234
}
 
235
 
 
236
/*
 
237
 * Pull the data from the FBO down to the pixmap
 
238
 */
 
239
void
 
240
glamor_download_pixmap(PixmapPtr pixmap)
 
241
{
 
242
    BoxRec      box;
 
243
 
 
244
    box.x1 = 0;
 
245
    box.x2 = pixmap->drawable.width;
 
246
    box.y1 = 0;
 
247
    box.y2 = pixmap->drawable.height;
 
248
 
 
249
    glamor_download_boxes(pixmap, &box, 1, 0, 0, 0, 0,
 
250
                          pixmap->devPrivate.ptr, pixmap->devKind);
 
251
}