xserver

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

glamor_transfer.c (7728B)


      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 /*
     27  * Write a region of bits into a pixmap
     28  */
     29 void
     30 glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
     31                     int dx_src, int dy_src,
     32                     int dx_dst, int dy_dst,
     33                     uint8_t *bits, uint32_t byte_stride)
     34 {
     35     ScreenPtr                   screen = pixmap->drawable.pScreen;
     36     glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
     37     glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
     38     int                         box_index;
     39     int                         bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
     40     const struct glamor_format *f = glamor_format_for_pixmap(pixmap);
     41 
     42     glamor_make_current(glamor_priv);
     43 
     44     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
     45 
     46     if (glamor_priv->has_unpack_subimage)
     47         glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
     48 
     49     glamor_pixmap_loop(priv, box_index) {
     50         BoxPtr                  box = glamor_pixmap_box_at(priv, box_index);
     51         glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_index);
     52         BoxPtr                  boxes = in_boxes;
     53         int                     nbox = in_nbox;
     54 
     55         glamor_bind_texture(glamor_priv, GL_TEXTURE0, fbo, TRUE);
     56 
     57         while (nbox--) {
     58 
     59             /* compute drawable coordinates */
     60             int x1 = MAX(boxes->x1 + dx_dst, box->x1);
     61             int x2 = MIN(boxes->x2 + dx_dst, box->x2);
     62             int y1 = MAX(boxes->y1 + dy_dst, box->y1);
     63             int y2 = MIN(boxes->y2 + dy_dst, box->y2);
     64 
     65             size_t ofs = (y1 - dy_dst + dy_src) * byte_stride;
     66             ofs += (x1 - dx_dst + dx_src) * bytes_per_pixel;
     67 
     68             boxes++;
     69 
     70             if (x2 <= x1 || y2 <= y1)
     71                 continue;
     72 
     73             if (glamor_priv->has_unpack_subimage ||
     74                 x2 - x1 == byte_stride / bytes_per_pixel) {
     75                 glTexSubImage2D(GL_TEXTURE_2D, 0,
     76                                 x1 - box->x1, y1 - box->y1,
     77                                 x2 - x1, y2 - y1,
     78                                 f->format, f->type,
     79                                 bits + ofs);
     80             } else {
     81                 for (; y1 < y2; y1++, ofs += byte_stride)
     82                     glTexSubImage2D(GL_TEXTURE_2D, 0,
     83                                     x1 - box->x1, y1 - box->y1,
     84                                     x2 - x1, 1,
     85                                     f->format, f->type,
     86                                     bits + ofs);
     87             }
     88         }
     89     }
     90 
     91     if (glamor_priv->has_unpack_subimage)
     92         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
     93 }
     94 
     95 /*
     96  * Upload a region of data
     97  */
     98 
     99 void
    100 glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
    101                      int region_x, int region_y,
    102                      uint8_t *bits, uint32_t byte_stride)
    103 {
    104     glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
    105                         -region_x, -region_y,
    106                         0, 0,
    107                         bits, byte_stride);
    108 }
    109 
    110 /*
    111  * Take the data in the pixmap and stuff it back into the FBO
    112  */
    113 void
    114 glamor_upload_pixmap(PixmapPtr pixmap)
    115 {
    116     BoxRec box;
    117 
    118     box.x1 = 0;
    119     box.x2 = pixmap->drawable.width;
    120     box.y1 = 0;
    121     box.y2 = pixmap->drawable.height;
    122     glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
    123                         pixmap->devPrivate.ptr, pixmap->devKind);
    124 }
    125 
    126 /*
    127  * Read stuff from the pixmap FBOs and write to memory
    128  */
    129 void
    130 glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
    131                       int dx_src, int dy_src,
    132                       int dx_dst, int dy_dst,
    133                       uint8_t *bits, uint32_t byte_stride)
    134 {
    135     ScreenPtr screen = pixmap->drawable.pScreen;
    136     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    137     glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
    138     int box_index;
    139     int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
    140     const struct glamor_format *f = glamor_format_for_pixmap(pixmap);
    141 
    142     glamor_make_current(glamor_priv);
    143 
    144     glPixelStorei(GL_PACK_ALIGNMENT, 4);
    145     if (glamor_priv->has_pack_subimage)
    146         glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
    147 
    148     glamor_pixmap_loop(priv, box_index) {
    149         BoxPtr                  box = glamor_pixmap_box_at(priv, box_index);
    150         glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_index);
    151         BoxPtr                  boxes = in_boxes;
    152         int                     nbox = in_nbox;
    153 
    154         /* This should not be called on GLAMOR_FBO_NO_FBO-allocated pixmaps. */
    155         assert(fbo->fb);
    156         glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
    157 
    158         while (nbox--) {
    159 
    160             /* compute drawable coordinates */
    161             int                     x1 = MAX(boxes->x1 + dx_src, box->x1);
    162             int                     x2 = MIN(boxes->x2 + dx_src, box->x2);
    163             int                     y1 = MAX(boxes->y1 + dy_src, box->y1);
    164             int                     y2 = MIN(boxes->y2 + dy_src, box->y2);
    165             size_t ofs = (y1 - dy_src + dy_dst) * byte_stride;
    166             ofs += (x1 - dx_src + dx_dst) * bytes_per_pixel;
    167 
    168             boxes++;
    169 
    170             if (x2 <= x1 || y2 <= y1)
    171                 continue;
    172 
    173             if (glamor_priv->has_pack_subimage ||
    174                 x2 - x1 == byte_stride / bytes_per_pixel) {
    175                 glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, f->format, f->type, bits + ofs);
    176             } else {
    177                 for (; y1 < y2; y1++, ofs += byte_stride)
    178                     glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, f->format, f->type, bits + ofs);
    179             }
    180         }
    181     }
    182     if (glamor_priv->has_pack_subimage)
    183         glPixelStorei(GL_PACK_ROW_LENGTH, 0);
    184 }
    185 
    186 /*
    187  * Read data from the pixmap FBO
    188  */
    189 void
    190 glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits)
    191 {
    192     BoxRec      box;
    193 
    194     box.x1 = x;
    195     box.x2 = x + w;
    196     box.y1 = y;
    197     box.y2 = y + h;
    198 
    199     glamor_download_boxes(pixmap, &box, 1, 0, 0, -x, -y,
    200                           bits, PixmapBytePad(w, pixmap->drawable.depth));
    201 }
    202 
    203 /*
    204  * Pull the data from the FBO down to the pixmap
    205  */
    206 void
    207 glamor_download_pixmap(PixmapPtr pixmap)
    208 {
    209     BoxRec      box;
    210 
    211     box.x1 = 0;
    212     box.x2 = pixmap->drawable.width;
    213     box.y1 = 0;
    214     box.y2 = pixmap->drawable.height;
    215 
    216     glamor_download_boxes(pixmap, &box, 1, 0, 0, 0, 0,
    217                           pixmap->devPrivate.ptr, pixmap->devKind);
    218 }