xserver

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

glamor_copy.c (26314B)


      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 #include "glamor_prepare.h"
     26 #include "glamor_transform.h"
     27 
     28 struct copy_args {
     29     PixmapPtr           src_pixmap;
     30     glamor_pixmap_fbo   *src;
     31     uint32_t            bitplane;
     32     int                 dx, dy;
     33 };
     34 
     35 static Bool
     36 use_copyarea(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg)
     37 {
     38     struct copy_args *args = arg;
     39     glamor_pixmap_fbo *src = args->src;
     40 
     41     glamor_bind_texture(glamor_get_screen_private(dst->drawable.pScreen),
     42                         GL_TEXTURE0, src, TRUE);
     43 
     44     glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
     45     glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height);
     46 
     47     return TRUE;
     48 }
     49 
     50 static const glamor_facet glamor_facet_copyarea = {
     51     "copy_area",
     52     .vs_vars = "attribute vec2 primitive;\n",
     53     .vs_exec = (GLAMOR_POS(gl_Position, primitive.xy)
     54                 "       fill_pos = (fill_offset + primitive.xy) * fill_size_inv;\n"),
     55     .fs_exec = "       gl_FragColor = texture2D(sampler, fill_pos);\n",
     56     .locations = glamor_program_location_fillsamp | glamor_program_location_fillpos,
     57     .use = use_copyarea,
     58 };
     59 
     60 /*
     61  * Configure the copy plane program for the current operation
     62  */
     63 
     64 static Bool
     65 use_copyplane(PixmapPtr dst, GCPtr gc, glamor_program *prog, void *arg)
     66 {
     67     struct copy_args *args = arg;
     68     glamor_pixmap_fbo *src = args->src;
     69 
     70     glamor_bind_texture(glamor_get_screen_private(dst->drawable.pScreen),
     71                         GL_TEXTURE0, src, TRUE);
     72 
     73     glUniform2f(prog->fill_offset_uniform, args->dx, args->dy);
     74     glUniform2f(prog->fill_size_inv_uniform, 1.0f/src->width, 1.0f/src->height);
     75 
     76     glamor_set_color(dst, gc->fgPixel, prog->fg_uniform);
     77     glamor_set_color(dst, gc->bgPixel, prog->bg_uniform);
     78 
     79     /* XXX handle 2 10 10 10 and 1555 formats; presumably the pixmap private knows this? */
     80     switch (args->src_pixmap->drawable.depth) {
     81     case 30:
     82         glUniform4ui(prog->bitplane_uniform,
     83                      (args->bitplane >> 20) & 0x3ff,
     84                      (args->bitplane >> 10) & 0x3ff,
     85                      (args->bitplane      ) & 0x3ff,
     86                      0);
     87 
     88         glUniform4f(prog->bitmul_uniform, 0x3ff, 0x3ff, 0x3ff, 0);
     89         break;
     90     case 24:
     91         glUniform4ui(prog->bitplane_uniform,
     92                      (args->bitplane >> 16) & 0xff,
     93                      (args->bitplane >>  8) & 0xff,
     94                      (args->bitplane      ) & 0xff,
     95                      0);
     96 
     97         glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0);
     98         break;
     99     case 32:
    100         glUniform4ui(prog->bitplane_uniform,
    101                      (args->bitplane >> 16) & 0xff,
    102                      (args->bitplane >>  8) & 0xff,
    103                      (args->bitplane      ) & 0xff,
    104                      (args->bitplane >> 24) & 0xff);
    105 
    106         glUniform4f(prog->bitmul_uniform, 0xff, 0xff, 0xff, 0xff);
    107         break;
    108     case 16:
    109         glUniform4ui(prog->bitplane_uniform,
    110                      (args->bitplane >> 11) & 0x1f,
    111                      (args->bitplane >>  5) & 0x3f,
    112                      (args->bitplane      ) & 0x1f,
    113                      0);
    114 
    115         glUniform4f(prog->bitmul_uniform, 0x1f, 0x3f, 0x1f, 0);
    116         break;
    117     case 15:
    118         glUniform4ui(prog->bitplane_uniform,
    119                      (args->bitplane >> 10) & 0x1f,
    120                      (args->bitplane >>  5) & 0x1f,
    121                      (args->bitplane      ) & 0x1f,
    122                      0);
    123 
    124         glUniform4f(prog->bitmul_uniform, 0x1f, 0x1f, 0x1f, 0);
    125         break;
    126     case 8:
    127         glUniform4ui(prog->bitplane_uniform,
    128                      0, 0, 0, args->bitplane);
    129         glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
    130         break;
    131     case 1:
    132         glUniform4ui(prog->bitplane_uniform,
    133                      0, 0, 0, args->bitplane);
    134         glUniform4f(prog->bitmul_uniform, 0, 0, 0, 0xff);
    135         break;
    136     }
    137 
    138     return TRUE;
    139 }
    140 
    141 static const glamor_facet glamor_facet_copyplane = {
    142     "copy_plane",
    143     .version = 130,
    144     .vs_vars = "attribute vec2 primitive;\n",
    145     .vs_exec = (GLAMOR_POS(gl_Position, (primitive.xy))
    146                 "       fill_pos = (fill_offset + primitive.xy) * fill_size_inv;\n"),
    147     .fs_exec = ("       uvec4 bits = uvec4(round(texture2D(sampler, fill_pos) * bitmul));\n"
    148                 "       if ((bits & bitplane) != uvec4(0,0,0,0))\n"
    149                 "               gl_FragColor = fg;\n"
    150                 "       else\n"
    151                 "               gl_FragColor = bg;\n"),
    152     .locations = glamor_program_location_fillsamp|glamor_program_location_fillpos|glamor_program_location_fg|glamor_program_location_bg|glamor_program_location_bitplane,
    153     .use = use_copyplane,
    154 };
    155 
    156 /*
    157  * When all else fails, pull the bits out of the GPU and do the
    158  * operation with fb
    159  */
    160 
    161 static void
    162 glamor_copy_bail(DrawablePtr src,
    163                  DrawablePtr dst,
    164                  GCPtr gc,
    165                  BoxPtr box,
    166                  int nbox,
    167                  int dx,
    168                  int dy,
    169                  Bool reverse,
    170                  Bool upsidedown,
    171                  Pixel bitplane,
    172                  void *closure)
    173 {
    174     if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) && glamor_prepare_access(src, GLAMOR_ACCESS_RO)) {
    175         if (bitplane) {
    176             if (src->bitsPerPixel > 1)
    177                 fbCopyNto1(src, dst, gc, box, nbox, dx, dy,
    178                            reverse, upsidedown, bitplane, closure);
    179             else
    180                 fbCopy1toN(src, dst, gc, box, nbox, dx, dy,
    181                            reverse, upsidedown, bitplane, closure);
    182         } else {
    183             fbCopyNtoN(src, dst, gc, box, nbox, dx, dy,
    184                        reverse, upsidedown, bitplane, closure);
    185         }
    186     }
    187     glamor_finish_access(dst);
    188     glamor_finish_access(src);
    189 }
    190 
    191 /**
    192  * Implements CopyPlane and CopyArea from the CPU to the GPU by using
    193  * the source as a texture and painting that into the destination.
    194  *
    195  * This requires that source and dest are different textures, or that
    196  * (if the copy area doesn't overlap), GL_NV_texture_barrier is used
    197  * to ensure that the caches are flushed at the right times.
    198  */
    199 static Bool
    200 glamor_copy_cpu_fbo(DrawablePtr src,
    201                     DrawablePtr dst,
    202                     GCPtr gc,
    203                     BoxPtr box,
    204                     int nbox,
    205                     int dx,
    206                     int dy,
    207                     Bool reverse,
    208                     Bool upsidedown,
    209                     Pixel bitplane,
    210                     void *closure)
    211 {
    212     ScreenPtr screen = dst->pScreen;
    213     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    214     PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
    215     int dst_xoff, dst_yoff;
    216 
    217     if (gc && gc->alu != GXcopy)
    218         goto bail;
    219 
    220     if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask))
    221         goto bail;
    222 
    223     glamor_make_current(glamor_priv);
    224 
    225     if (!glamor_prepare_access(src, GLAMOR_ACCESS_RO))
    226         goto bail;
    227 
    228     glamor_get_drawable_deltas(dst, dst_pixmap, &dst_xoff, &dst_yoff);
    229 
    230     if (bitplane) {
    231         FbBits *tmp_bits;
    232         FbStride tmp_stride;
    233         int tmp_bpp;
    234         int tmp_xoff, tmp_yoff;
    235 
    236         PixmapPtr tmp_pix = fbCreatePixmap(screen, dst_pixmap->drawable.width,
    237                                            dst_pixmap->drawable.height,
    238                                            dst->depth, 0);
    239 
    240         if (!tmp_pix) {
    241             glamor_finish_access(src);
    242             goto bail;
    243         }
    244 
    245         tmp_pix->drawable.x = dst_xoff;
    246         tmp_pix->drawable.y = dst_yoff;
    247 
    248         fbGetDrawable(&tmp_pix->drawable, tmp_bits, tmp_stride, tmp_bpp, tmp_xoff,
    249                       tmp_yoff);
    250 
    251         if (src->bitsPerPixel > 1)
    252             fbCopyNto1(src, &tmp_pix->drawable, gc, box, nbox, dx, dy,
    253                        reverse, upsidedown, bitplane, closure);
    254         else
    255             fbCopy1toN(src, &tmp_pix->drawable, gc, box, nbox, dx, dy,
    256                        reverse, upsidedown, bitplane, closure);
    257 
    258         glamor_upload_boxes(dst_pixmap, box, nbox, tmp_xoff, tmp_yoff,
    259                             dst_xoff, dst_yoff, (uint8_t *) tmp_bits,
    260                             tmp_stride * sizeof(FbBits));
    261         fbDestroyPixmap(tmp_pix);
    262     } else {
    263         FbBits *src_bits;
    264         FbStride src_stride;
    265         int src_bpp;
    266         int src_xoff, src_yoff;
    267 
    268         fbGetDrawable(src, src_bits, src_stride, src_bpp, src_xoff, src_yoff);
    269         glamor_upload_boxes(dst_pixmap, box, nbox, src_xoff + dx, src_yoff + dy,
    270                             dst_xoff, dst_yoff,
    271                             (uint8_t *) src_bits, src_stride * sizeof (FbBits));
    272     }
    273     glamor_finish_access(src);
    274 
    275     return TRUE;
    276 
    277 bail:
    278     return FALSE;
    279 }
    280 
    281 /**
    282  * Implements CopyArea from the GPU to the CPU using glReadPixels from the
    283  * source FBO.
    284  */
    285 static Bool
    286 glamor_copy_fbo_cpu(DrawablePtr src,
    287                     DrawablePtr dst,
    288                     GCPtr gc,
    289                     BoxPtr box,
    290                     int nbox,
    291                     int dx,
    292                     int dy,
    293                     Bool reverse,
    294                     Bool upsidedown,
    295                     Pixel bitplane,
    296                     void *closure)
    297 {
    298     ScreenPtr screen = dst->pScreen;
    299     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    300     PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
    301     FbBits *dst_bits;
    302     FbStride dst_stride;
    303     int dst_bpp;
    304     int src_xoff, src_yoff;
    305     int dst_xoff, dst_yoff;
    306 
    307     if (gc && gc->alu != GXcopy)
    308         goto bail;
    309 
    310     if (gc && !glamor_pm_is_solid(gc->depth, gc->planemask))
    311         goto bail;
    312 
    313     glamor_make_current(glamor_priv);
    314 
    315     if (!glamor_prepare_access(dst, GLAMOR_ACCESS_RW))
    316         goto bail;
    317 
    318     glamor_get_drawable_deltas(src, src_pixmap, &src_xoff, &src_yoff);
    319 
    320     fbGetDrawable(dst, dst_bits, dst_stride, dst_bpp, dst_xoff, dst_yoff);
    321 
    322     glamor_download_boxes(src_pixmap, box, nbox, src_xoff + dx, src_yoff + dy,
    323                           dst_xoff, dst_yoff,
    324                           (uint8_t *) dst_bits, dst_stride * sizeof (FbBits));
    325     glamor_finish_access(dst);
    326 
    327     return TRUE;
    328 
    329 bail:
    330     return FALSE;
    331 }
    332 
    333 /* Include the enums here for the moment, to keep from needing to bump epoxy. */
    334 #ifndef GL_TILE_RASTER_ORDER_FIXED_MESA
    335 #define GL_TILE_RASTER_ORDER_FIXED_MESA          0x8BB8
    336 #define GL_TILE_RASTER_ORDER_INCREASING_X_MESA   0x8BB9
    337 #define GL_TILE_RASTER_ORDER_INCREASING_Y_MESA   0x8BBA
    338 #endif
    339 
    340 /*
    341  * Copy from GPU to GPU by using the source
    342  * as a texture and painting that into the destination
    343  */
    344 
    345 static Bool
    346 glamor_copy_fbo_fbo_draw(DrawablePtr src,
    347                          DrawablePtr dst,
    348                          GCPtr gc,
    349                          BoxPtr box,
    350                          int nbox,
    351                          int dx,
    352                          int dy,
    353                          Bool reverse,
    354                          Bool upsidedown,
    355                          Pixel bitplane,
    356                          void *closure)
    357 {
    358     ScreenPtr screen = dst->pScreen;
    359     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    360     PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
    361     PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
    362     glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
    363     glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
    364     int src_box_index, dst_box_index;
    365     int dst_off_x, dst_off_y;
    366     int src_off_x, src_off_y;
    367     GLshort *v;
    368     char *vbo_offset;
    369     struct copy_args args;
    370     glamor_program *prog;
    371     const glamor_facet *copy_facet;
    372     int n;
    373     Bool ret = FALSE;
    374     BoxRec bounds = glamor_no_rendering_bounds();
    375 
    376     glamor_make_current(glamor_priv);
    377 
    378     if (gc && !glamor_set_planemask(gc->depth, gc->planemask))
    379         goto bail_ctx;
    380 
    381     if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
    382         goto bail_ctx;
    383 
    384     if (bitplane && !glamor_priv->can_copyplane)
    385         goto bail_ctx;
    386 
    387     if (bitplane) {
    388         prog = &glamor_priv->copy_plane_prog;
    389         copy_facet = &glamor_facet_copyplane;
    390     } else {
    391         prog = &glamor_priv->copy_area_prog;
    392         copy_facet = &glamor_facet_copyarea;
    393     }
    394 
    395     if (prog->failed)
    396         goto bail_ctx;
    397 
    398     if (!prog->prog) {
    399         if (!glamor_build_program(screen, prog,
    400                                   copy_facet, NULL, NULL, NULL))
    401             goto bail_ctx;
    402     }
    403 
    404     args.src_pixmap = src_pixmap;
    405     args.bitplane = bitplane;
    406 
    407     /* Set up the vertex buffers for the points */
    408 
    409     v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset);
    410 
    411     if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) {
    412         glEnable(GL_TILE_RASTER_ORDER_FIXED_MESA);
    413         if (dx >= 0)
    414             glEnable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA);
    415         else
    416             glDisable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA);
    417         if (dy >= 0)
    418             glEnable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA);
    419         else
    420             glDisable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA);
    421     }
    422 
    423     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
    424     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
    425                           2 * sizeof (GLshort), vbo_offset);
    426 
    427     if (nbox < 100) {
    428         bounds = glamor_start_rendering_bounds();
    429         for (int i = 0; i < nbox; i++)
    430             glamor_bounds_union_box(&bounds, &box[i]);
    431     }
    432 
    433     for (n = 0; n < nbox; n++) {
    434         v[0] = box->x1; v[1] = box->y1;
    435         v[2] = box->x1; v[3] = box->y2;
    436         v[4] = box->x2; v[5] = box->y2;
    437         v[6] = box->x2; v[7] = box->y1;
    438 
    439         v += 8;
    440         box++;
    441     }
    442 
    443     glamor_put_vbo_space(screen);
    444 
    445     glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
    446 
    447     glEnable(GL_SCISSOR_TEST);
    448 
    449     glamor_pixmap_loop(src_priv, src_box_index) {
    450         BoxPtr src_box = glamor_pixmap_box_at(src_priv, src_box_index);
    451 
    452         args.dx = dx + src_off_x - src_box->x1;
    453         args.dy = dy + src_off_y - src_box->y1;
    454         args.src = glamor_pixmap_fbo_at(src_priv, src_box_index);
    455 
    456         if (!glamor_use_program(dst_pixmap, gc, prog, &args))
    457             goto bail_ctx;
    458 
    459         glamor_pixmap_loop(dst_priv, dst_box_index) {
    460             BoxRec scissor = {
    461                 .x1 = max(-args.dx, bounds.x1),
    462                 .y1 = max(-args.dy, bounds.y1),
    463                 .x2 = min(-args.dx + src_box->x2 - src_box->x1, bounds.x2),
    464                 .y2 = min(-args.dy + src_box->y2 - src_box->y1, bounds.y2),
    465             };
    466             if (scissor.x1 >= scissor.x2 || scissor.y1 >= scissor.y2)
    467                 continue;
    468 
    469             if (!glamor_set_destination_drawable(dst, dst_box_index, FALSE, FALSE,
    470                                                  prog->matrix_uniform,
    471                                                  &dst_off_x, &dst_off_y))
    472                 goto bail_ctx;
    473 
    474             glScissor(scissor.x1 + dst_off_x,
    475                       scissor.y1 + dst_off_y,
    476                       scissor.x2 - scissor.x1,
    477                       scissor.y2 - scissor.y1);
    478 
    479             glamor_glDrawArrays_GL_QUADS(glamor_priv, nbox);
    480         }
    481     }
    482 
    483     ret = TRUE;
    484 
    485 bail_ctx:
    486     if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) {
    487         glDisable(GL_TILE_RASTER_ORDER_FIXED_MESA);
    488     }
    489     glDisable(GL_SCISSOR_TEST);
    490     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
    491 
    492     return ret;
    493 }
    494 
    495 /**
    496  * Copies from the GPU to the GPU using a temporary pixmap in between,
    497  * to correctly handle overlapping copies.
    498  */
    499 
    500 static Bool
    501 glamor_copy_fbo_fbo_temp(DrawablePtr src,
    502                          DrawablePtr dst,
    503                          GCPtr gc,
    504                          BoxPtr box,
    505                          int nbox,
    506                          int dx,
    507                          int dy,
    508                          Bool reverse,
    509                          Bool upsidedown,
    510                          Pixel bitplane,
    511                          void *closure)
    512 {
    513     ScreenPtr screen = dst->pScreen;
    514     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    515     PixmapPtr tmp_pixmap;
    516     BoxRec bounds;
    517     int n;
    518     BoxPtr tmp_box;
    519 
    520     if (nbox == 0)
    521         return TRUE;
    522 
    523     /* Sanity check state to avoid getting halfway through and bailing
    524      * at the last second. Might be nice to have checks that didn't
    525      * involve setting state.
    526      */
    527     glamor_make_current(glamor_priv);
    528 
    529     if (gc && !glamor_set_planemask(gc->depth, gc->planemask))
    530         goto bail_ctx;
    531 
    532     if (!glamor_set_alu(screen, gc ? gc->alu : GXcopy))
    533         goto bail_ctx;
    534 
    535     /* Find the size of the area to copy
    536      */
    537     bounds = box[0];
    538     for (n = 1; n < nbox; n++) {
    539         bounds.x1 = min(bounds.x1, box[n].x1);
    540         bounds.x2 = max(bounds.x2, box[n].x2);
    541         bounds.y1 = min(bounds.y1, box[n].y1);
    542         bounds.y2 = max(bounds.y2, box[n].y2);
    543     }
    544 
    545     /* Allocate a suitable temporary pixmap
    546      */
    547     tmp_pixmap = glamor_create_pixmap(screen,
    548                                       bounds.x2 - bounds.x1,
    549                                       bounds.y2 - bounds.y1,
    550                                       src->depth, 0);
    551     if (!tmp_pixmap)
    552         goto bail;
    553 
    554     tmp_box = calloc(nbox, sizeof (BoxRec));
    555     if (!tmp_box)
    556         goto bail_pixmap;
    557 
    558     /* Convert destination boxes into tmp pixmap boxes
    559      */
    560     for (n = 0; n < nbox; n++) {
    561         tmp_box[n].x1 = box[n].x1 - bounds.x1;
    562         tmp_box[n].x2 = box[n].x2 - bounds.x1;
    563         tmp_box[n].y1 = box[n].y1 - bounds.y1;
    564         tmp_box[n].y2 = box[n].y2 - bounds.y1;
    565     }
    566 
    567     if (!glamor_copy_fbo_fbo_draw(src,
    568                                   &tmp_pixmap->drawable,
    569                                   NULL,
    570                                   tmp_box,
    571                                   nbox,
    572                                   dx + bounds.x1,
    573                                   dy + bounds.y1,
    574                                   FALSE, FALSE,
    575                                   0, NULL))
    576         goto bail_box;
    577 
    578     if (!glamor_copy_fbo_fbo_draw(&tmp_pixmap->drawable,
    579                                   dst,
    580                                   gc,
    581                                   box,
    582                                   nbox,
    583                                   -bounds.x1,
    584                                   -bounds.y1,
    585                                   FALSE, FALSE,
    586                                   bitplane, closure))
    587         goto bail_box;
    588 
    589     free(tmp_box);
    590 
    591     glamor_destroy_pixmap(tmp_pixmap);
    592 
    593     return TRUE;
    594 bail_box:
    595     free(tmp_box);
    596 bail_pixmap:
    597     glamor_destroy_pixmap(tmp_pixmap);
    598 bail:
    599     return FALSE;
    600 
    601 bail_ctx:
    602     return FALSE;
    603 }
    604 
    605 /**
    606  * Returns TRUE if the copy has to be implemented with
    607  * glamor_copy_fbo_fbo_temp() instead of glamor_copy_fbo_fbo().
    608  *
    609  * If the src and dst are in the same pixmap, then glamor_copy_fbo_fbo()'s
    610  * sampling would give undefined results (since the same texture would be
    611  * bound as an FBO destination and as a texture source).  However, if we
    612  * have GL_NV_texture_barrier, we can take advantage of the exception it
    613  * added:
    614  *
    615  *    "- If a texel has been written, then in order to safely read the result
    616  *       a texel fetch must be in a subsequent Draw separated by the command
    617  *
    618  *       void TextureBarrierNV(void);
    619  *
    620  *    TextureBarrierNV() will guarantee that writes have completed and caches
    621  *    have been invalidated before subsequent Draws are executed."
    622  */
    623 static Bool
    624 glamor_copy_needs_temp(DrawablePtr src,
    625                        DrawablePtr dst,
    626                        BoxPtr box,
    627                        int nbox,
    628                        int dx,
    629                        int dy)
    630 {
    631     PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
    632     PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
    633     ScreenPtr screen = dst->pScreen;
    634     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    635     int n;
    636     int dst_off_x, dst_off_y;
    637     int src_off_x, src_off_y;
    638     BoxRec bounds;
    639 
    640     if (src_pixmap != dst_pixmap)
    641         return FALSE;
    642 
    643     if (nbox == 0)
    644         return FALSE;
    645 
    646     if (!glamor_priv->has_nv_texture_barrier)
    647         return TRUE;
    648 
    649     if (!glamor_priv->has_mesa_tile_raster_order) {
    650         glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
    651         glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y);
    652 
    653         bounds = box[0];
    654         for (n = 1; n < nbox; n++) {
    655             bounds.x1 = min(bounds.x1, box[n].x1);
    656             bounds.y1 = min(bounds.y1, box[n].y1);
    657 
    658             bounds.x2 = max(bounds.x2, box[n].x2);
    659             bounds.y2 = max(bounds.y2, box[n].y2);
    660         }
    661 
    662         /* Check to see if the pixmap-relative boxes overlap in both X and Y,
    663          * in which case we can't rely on NV_texture_barrier and must
    664          * make a temporary copy
    665          *
    666          *  dst.x1                     < src.x2 &&
    667          *  src.x1                     < dst.x2 &&
    668          *
    669          *  dst.y1                     < src.y2 &&
    670          *  src.y1                     < dst.y2
    671          */
    672         if (bounds.x1 + dst_off_x      < bounds.x2 + dx + src_off_x &&
    673             bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x &&
    674 
    675             bounds.y1 + dst_off_y      < bounds.y2 + dy + src_off_y &&
    676             bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) {
    677             return TRUE;
    678         }
    679     }
    680 
    681     glTextureBarrierNV();
    682 
    683     return FALSE;
    684 }
    685 
    686 static Bool
    687 glamor_copy_gl(DrawablePtr src,
    688                DrawablePtr dst,
    689                GCPtr gc,
    690                BoxPtr box,
    691                int nbox,
    692                int dx,
    693                int dy,
    694                Bool reverse,
    695                Bool upsidedown,
    696                Pixel bitplane,
    697                void *closure)
    698 {
    699     PixmapPtr src_pixmap = glamor_get_drawable_pixmap(src);
    700     PixmapPtr dst_pixmap = glamor_get_drawable_pixmap(dst);
    701     glamor_pixmap_private *src_priv = glamor_get_pixmap_private(src_pixmap);
    702     glamor_pixmap_private *dst_priv = glamor_get_pixmap_private(dst_pixmap);
    703 
    704     if (GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_priv)) {
    705         if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv)) {
    706             if (glamor_copy_needs_temp(src, dst, box, nbox, dx, dy))
    707                 return glamor_copy_fbo_fbo_temp(src, dst, gc, box, nbox, dx, dy,
    708                                                 reverse, upsidedown, bitplane, closure);
    709             else
    710                 return glamor_copy_fbo_fbo_draw(src, dst, gc, box, nbox, dx, dy,
    711                                                 reverse, upsidedown, bitplane, closure);
    712         }
    713 
    714         return glamor_copy_cpu_fbo(src, dst, gc, box, nbox, dx, dy,
    715                                    reverse, upsidedown, bitplane, closure);
    716     } else if (GLAMOR_PIXMAP_PRIV_HAS_FBO(src_priv) &&
    717                dst_priv->type != GLAMOR_DRM_ONLY &&
    718                bitplane == 0) {
    719             return glamor_copy_fbo_cpu(src, dst, gc, box, nbox, dx, dy,
    720                                        reverse, upsidedown, bitplane, closure);
    721     }
    722     return FALSE;
    723 }
    724 
    725 void
    726 glamor_copy(DrawablePtr src,
    727             DrawablePtr dst,
    728             GCPtr gc,
    729             BoxPtr box,
    730             int nbox,
    731             int dx,
    732             int dy,
    733             Bool reverse,
    734             Bool upsidedown,
    735             Pixel bitplane,
    736             void *closure)
    737 {
    738     if (nbox == 0)
    739 	return;
    740 
    741     if (glamor_copy_gl(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure))
    742         return;
    743     glamor_copy_bail(src, dst, gc, box, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
    744 }
    745 
    746 RegionPtr
    747 glamor_copy_area(DrawablePtr src, DrawablePtr dst, GCPtr gc,
    748                  int srcx, int srcy, int width, int height, int dstx, int dsty)
    749 {
    750     return miDoCopy(src, dst, gc,
    751                     srcx, srcy, width, height,
    752                     dstx, dsty, glamor_copy, 0, NULL);
    753 }
    754 
    755 RegionPtr
    756 glamor_copy_plane(DrawablePtr src, DrawablePtr dst, GCPtr gc,
    757                   int srcx, int srcy, int width, int height, int dstx, int dsty,
    758                   unsigned long bitplane)
    759 {
    760     if ((bitplane & FbFullMask(src->depth)) == 0)
    761         return miHandleExposures(src, dst, gc,
    762                                  srcx, srcy, width, height, dstx, dsty);
    763     return miDoCopy(src, dst, gc,
    764                     srcx, srcy, width, height,
    765                     dstx, dsty, glamor_copy, bitplane, NULL);
    766 }
    767 
    768 void
    769 glamor_copy_window(WindowPtr window, DDXPointRec old_origin, RegionPtr src_region)
    770 {
    771     PixmapPtr pixmap = glamor_get_drawable_pixmap(&window->drawable);
    772     DrawablePtr drawable = &pixmap->drawable;
    773     RegionRec dst_region;
    774     int dx, dy;
    775 
    776     dx = old_origin.x - window->drawable.x;
    777     dy = old_origin.y - window->drawable.y;
    778     RegionTranslate(src_region, -dx, -dy);
    779 
    780     RegionNull(&dst_region);
    781 
    782     RegionIntersect(&dst_region, &window->borderClip, src_region);
    783 
    784 #ifdef COMPOSITE
    785     if (pixmap->screen_x || pixmap->screen_y)
    786         RegionTranslate(&dst_region, -pixmap->screen_x, -pixmap->screen_y);
    787 #endif
    788 
    789     miCopyRegion(drawable, drawable,
    790                  0, &dst_region, dx, dy, glamor_copy, 0, 0);
    791 
    792     RegionUninit(&dst_region);
    793 }