"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/glamor/glamor_prepare.c" (29 Mar 2020, 9591 Bytes) of package /linux/misc/xorg-server-1.20.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "glamor_prepare.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.20.7_vs_1.20.8.

    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             glamor_priv->suppress_gl_out_of_memory_logging = true;
   92 
   93             glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->pbo);
   94             glBufferData(GL_PIXEL_PACK_BUFFER,
   95                          pixmap->devKind * pixmap->drawable.height, NULL,
   96                          gl_usage);
   97 
   98             glamor_priv->suppress_gl_out_of_memory_logging = false;
   99 
  100             if (glGetError() == GL_OUT_OF_MEMORY) {
  101                 if (!glamor_priv->logged_any_pbo_allocation_failure) {
  102                     LogMessageVerb(X_WARNING, 0, "glamor: Failed to allocate %d "
  103                                    "bytes PBO due to GL_OUT_OF_MEMORY.\n",
  104                                    pixmap->devKind * pixmap->drawable.height);
  105                     glamor_priv->logged_any_pbo_allocation_failure = true;
  106                 }
  107                 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  108                 glDeleteBuffers(1, &priv->pbo);
  109                 priv->pbo = 0;
  110             }
  111         }
  112 
  113         if (!priv->pbo) {
  114             pixmap->devPrivate.ptr = xallocarray(pixmap->devKind,
  115                                                  pixmap->drawable.height);
  116             if (!pixmap->devPrivate.ptr)
  117                 return FALSE;
  118         }
  119         priv->map_access = access;
  120     }
  121 
  122     glamor_download_boxes(pixmap, RegionRects(&region), RegionNumRects(&region),
  123                           0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
  124 
  125     RegionUninit(&region);
  126 
  127     if (priv->pbo) {
  128         if (priv->map_access == GLAMOR_ACCESS_RW)
  129             gl_access = GL_READ_WRITE;
  130         else
  131             gl_access = GL_READ_ONLY;
  132 
  133         pixmap->devPrivate.ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
  134         glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
  135     }
  136 
  137     priv->prepared = TRUE;
  138     return TRUE;
  139 }
  140 
  141 /*
  142  * When we're done with the drawable, unmap the PBO, reupload
  143  * if we were writing to it and then unbind it to release the memory
  144  */
  145 
  146 static void
  147 glamor_fini_pixmap(PixmapPtr pixmap)
  148 {
  149     glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
  150 
  151     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
  152         return;
  153 
  154     if (!priv->prepared)
  155         return;
  156 
  157     if (priv->pbo) {
  158         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->pbo);
  159         glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
  160         pixmap->devPrivate.ptr = NULL;
  161     }
  162 
  163     if (priv->map_access == GLAMOR_ACCESS_RW) {
  164         glamor_upload_boxes(pixmap,
  165                             RegionRects(&priv->prepare_region),
  166                             RegionNumRects(&priv->prepare_region),
  167                             0, 0, 0, 0, pixmap->devPrivate.ptr, pixmap->devKind);
  168     }
  169 
  170     RegionUninit(&priv->prepare_region);
  171 
  172     if (priv->pbo) {
  173         glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
  174         glDeleteBuffers(1, &priv->pbo);
  175         priv->pbo = 0;
  176     } else {
  177         free(pixmap->devPrivate.ptr);
  178         pixmap->devPrivate.ptr = NULL;
  179     }
  180 
  181     priv->prepared = FALSE;
  182 }
  183 
  184 Bool
  185 glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
  186 {
  187     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  188     BoxRec box;
  189     int off_x, off_y;
  190 
  191     glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
  192 
  193     box.x1 = drawable->x + off_x;
  194     box.x2 = box.x1 + drawable->width;
  195     box.y1 = drawable->y + off_y;
  196     box.y2 = box.y1 + drawable->height;
  197     return glamor_prep_pixmap_box(pixmap, access, &box);
  198 }
  199 
  200 Bool
  201 glamor_prepare_access_box(DrawablePtr drawable, glamor_access_t access,
  202                          int x, int y, int w, int h)
  203 {
  204     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
  205     BoxRec box;
  206     int off_x, off_y;
  207 
  208     glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
  209     box.x1 = drawable->x + x + off_x;
  210     box.x2 = box.x1 + w;
  211     box.y1 = drawable->y + y + off_y;
  212     box.y2 = box.y1 + h;
  213     return glamor_prep_pixmap_box(pixmap, access, &box);
  214 }
  215 
  216 void
  217 glamor_finish_access(DrawablePtr drawable)
  218 {
  219     glamor_fini_pixmap(glamor_get_drawable_pixmap(drawable));
  220 }
  221 
  222 /*
  223  * Make a picture ready to use with fb.
  224  */
  225 
  226 Bool
  227 glamor_prepare_access_picture(PicturePtr picture, glamor_access_t access)
  228 {
  229     if (!picture || !picture->pDrawable)
  230         return TRUE;
  231 
  232     return glamor_prepare_access(picture->pDrawable, access);
  233 }
  234 
  235 Bool
  236 glamor_prepare_access_picture_box(PicturePtr picture, glamor_access_t access,
  237                         int x, int y, int w, int h)
  238 {
  239     if (!picture || !picture->pDrawable)
  240         return TRUE;
  241 
  242     /* If a transform is set, we don't know what the bounds is on the
  243      * source, so just prepare the whole pixmap.  XXX: We could
  244      * potentially work out where in the source would be sampled based
  245      * on the transform, and we don't need do do this for destination
  246      * pixmaps at all.
  247      */
  248     if (picture->transform) {
  249         return glamor_prepare_access_box(picture->pDrawable, access,
  250                                          0, 0,
  251                                          picture->pDrawable->width,
  252                                          picture->pDrawable->height);
  253     } else {
  254         return glamor_prepare_access_box(picture->pDrawable, access,
  255                                          x, y, w, h);
  256     }
  257 }
  258 
  259 void
  260 glamor_finish_access_picture(PicturePtr picture)
  261 {
  262     if (!picture || !picture->pDrawable)
  263         return;
  264 
  265     glamor_finish_access(picture->pDrawable);
  266 }
  267 
  268 /*
  269  * Make a GC ready to use with fb. This just
  270  * means making sure the appropriate fill pixmap is
  271  * in CPU memory again
  272  */
  273 
  274 Bool
  275 glamor_prepare_access_gc(GCPtr gc)
  276 {
  277     switch (gc->fillStyle) {
  278     case FillTiled:
  279         return glamor_prepare_access(&gc->tile.pixmap->drawable,
  280                                      GLAMOR_ACCESS_RO);
  281     case FillStippled:
  282     case FillOpaqueStippled:
  283         return glamor_prepare_access(&gc->stipple->drawable, GLAMOR_ACCESS_RO);
  284     }
  285     return TRUE;
  286 }
  287 
  288 /*
  289  * Free any temporary CPU pixmaps for the GC
  290  */
  291 void
  292 glamor_finish_access_gc(GCPtr gc)
  293 {
  294     switch (gc->fillStyle) {
  295     case FillTiled:
  296         glamor_finish_access(&gc->tile.pixmap->drawable);
  297         break;
  298     case FillStippled:
  299     case FillOpaqueStippled:
  300         glamor_finish_access(&gc->stipple->drawable);
  301         break;
  302     }
  303 }