"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/glamor/glamor_fbo.c" (29 Mar 2020, 11034 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_fbo.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 © 2009 Intel Corporation
    3  * Copyright © 1998 Keith Packard
    4  *
    5  * Permission is hereby granted, free of charge, to any person obtaining a
    6  * copy of this software and associated documentation files (the "Software"),
    7  * to deal in the Software without restriction, including without limitation
    8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    9  * and/or sell copies of the Software, and to permit persons to whom the
   10  * Software is furnished to do so, subject to the following conditions:
   11  *
   12  * The above copyright notice and this permission notice (including the next
   13  * paragraph) shall be included in all copies or substantial portions of the
   14  * Software.
   15  *
   16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   22  * IN THE SOFTWARE.
   23  *
   24  * Authors:
   25  *    Zhigang Gong <zhigang.gong@gmail.com>
   26  *
   27  */
   28 
   29 #include <stdlib.h>
   30 
   31 #include "glamor_priv.h"
   32 
   33 void
   34 glamor_destroy_fbo(glamor_screen_private *glamor_priv,
   35                    glamor_pixmap_fbo *fbo)
   36 {
   37     glamor_make_current(glamor_priv);
   38 
   39     if (fbo->fb)
   40         glDeleteFramebuffers(1, &fbo->fb);
   41     if (fbo->tex)
   42         glDeleteTextures(1, &fbo->tex);
   43 
   44     free(fbo);
   45 }
   46 
   47 static int
   48 glamor_pixmap_ensure_fb(glamor_screen_private *glamor_priv,
   49                         glamor_pixmap_fbo *fbo)
   50 {
   51     int status, err = 0;
   52 
   53     glamor_make_current(glamor_priv);
   54 
   55     if (fbo->fb == 0)
   56         glGenFramebuffers(1, &fbo->fb);
   57     assert(fbo->tex != 0);
   58     glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
   59     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
   60                            GL_TEXTURE_2D, fbo->tex, 0);
   61     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
   62     if (status != GL_FRAMEBUFFER_COMPLETE) {
   63         const char *str;
   64 
   65         switch (status) {
   66         case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
   67             str = "incomplete attachment";
   68             break;
   69         case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
   70             str = "incomplete/missing attachment";
   71             break;
   72         case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
   73             str = "incomplete draw buffer";
   74             break;
   75         case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
   76             str = "incomplete read buffer";
   77             break;
   78         case GL_FRAMEBUFFER_UNSUPPORTED:
   79             str = "unsupported";
   80             break;
   81         case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
   82             str = "incomplete multiple";
   83             break;
   84         default:
   85             str = "unknown error";
   86             break;
   87         }
   88 
   89         glamor_fallback("glamor: Failed to create fbo, %s\n", str);
   90         err = -1;
   91     }
   92 
   93     return err;
   94 }
   95 
   96 glamor_pixmap_fbo *
   97 glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
   98                            int w, int h, GLenum format, GLint tex, int flag)
   99 {
  100     glamor_pixmap_fbo *fbo;
  101 
  102     fbo = calloc(1, sizeof(*fbo));
  103     if (fbo == NULL)
  104         return NULL;
  105 
  106     fbo->tex = tex;
  107     fbo->width = w;
  108     fbo->height = h;
  109     fbo->format = format;
  110 
  111     if (flag != GLAMOR_CREATE_FBO_NO_FBO) {
  112         if (glamor_pixmap_ensure_fb(glamor_priv, fbo) != 0) {
  113             glamor_destroy_fbo(glamor_priv, fbo);
  114             fbo = NULL;
  115         }
  116     }
  117 
  118     return fbo;
  119 }
  120 
  121 static int
  122 _glamor_create_tex(glamor_screen_private *glamor_priv,
  123                    int w, int h, GLenum format)
  124 {
  125     unsigned int tex;
  126     GLenum iformat = format;
  127 
  128     if (format == GL_RGB10_A2)
  129         format = GL_RGBA;
  130     glamor_make_current(glamor_priv);
  131     glGenTextures(1, &tex);
  132     glBindTexture(GL_TEXTURE_2D, tex);
  133     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  134     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  135     if (format == glamor_priv->one_channel_format && format == GL_RED)
  136         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
  137     glamor_priv->suppress_gl_out_of_memory_logging = true;
  138     glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0,
  139                  format, GL_UNSIGNED_BYTE, NULL);
  140     glamor_priv->suppress_gl_out_of_memory_logging = false;
  141 
  142     if (glGetError() == GL_OUT_OF_MEMORY) {
  143         if (!glamor_priv->logged_any_fbo_allocation_failure) {
  144             LogMessageVerb(X_WARNING, 0, "glamor: Failed to allocate %dx%d "
  145                            "FBO due to GL_OUT_OF_MEMORY.\n", w, h);
  146             LogMessageVerb(X_WARNING, 0,
  147                            "glamor: Expect reduced performance.\n");
  148             glamor_priv->logged_any_fbo_allocation_failure = true;
  149         }
  150         glDeleteTextures(1, &tex);
  151         return 0;
  152     }
  153 
  154     return tex;
  155 }
  156 
  157 glamor_pixmap_fbo *
  158 glamor_create_fbo(glamor_screen_private *glamor_priv,
  159                   int w, int h, GLenum format, int flag)
  160 {
  161     GLint tex = _glamor_create_tex(glamor_priv, w, h, format);
  162 
  163     if (!tex) /* Texture creation failed due to GL_OUT_OF_MEMORY */
  164         return NULL;
  165 
  166     return glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag);
  167 }
  168 
  169 /**
  170  * Create storage for the w * h region, using FBOs of the GL's maximum
  171  * supported size.
  172  */
  173 glamor_pixmap_fbo *
  174 glamor_create_fbo_array(glamor_screen_private *glamor_priv,
  175                          int w, int h, GLenum format, int flag,
  176                          int block_w, int block_h,
  177                          glamor_pixmap_private *priv)
  178 {
  179     int block_wcnt;
  180     int block_hcnt;
  181     glamor_pixmap_fbo **fbo_array;
  182     BoxPtr box_array;
  183     int i, j;
  184 
  185     priv->block_w = block_w;
  186     priv->block_h = block_h;
  187 
  188     block_wcnt = (w + block_w - 1) / block_w;
  189     block_hcnt = (h + block_h - 1) / block_h;
  190 
  191     box_array = calloc(block_wcnt * block_hcnt, sizeof(box_array[0]));
  192     if (box_array == NULL)
  193         return NULL;
  194 
  195     fbo_array = calloc(block_wcnt * block_hcnt, sizeof(glamor_pixmap_fbo *));
  196     if (fbo_array == NULL) {
  197         free(box_array);
  198         return FALSE;
  199     }
  200     for (i = 0; i < block_hcnt; i++) {
  201         int block_y1, block_y2;
  202         int fbo_w, fbo_h;
  203 
  204         block_y1 = i * block_h;
  205         block_y2 = (block_y1 + block_h) > h ? h : (block_y1 + block_h);
  206         fbo_h = block_y2 - block_y1;
  207 
  208         for (j = 0; j < block_wcnt; j++) {
  209             box_array[i * block_wcnt + j].x1 = j * block_w;
  210             box_array[i * block_wcnt + j].y1 = block_y1;
  211             box_array[i * block_wcnt + j].x2 =
  212                 (j + 1) * block_w > w ? w : (j + 1) * block_w;
  213             box_array[i * block_wcnt + j].y2 = block_y2;
  214             fbo_w =
  215                 box_array[i * block_wcnt + j].x2 - box_array[i * block_wcnt +
  216                                                              j].x1;
  217             fbo_array[i * block_wcnt + j] = glamor_create_fbo(glamor_priv,
  218                                                               fbo_w, fbo_h,
  219                                                               format,
  220                                                               GLAMOR_CREATE_PIXMAP_FIXUP);
  221             if (fbo_array[i * block_wcnt + j] == NULL)
  222                 goto cleanup;
  223         }
  224     }
  225 
  226     priv->box = box_array[0];
  227     priv->box_array = box_array;
  228     priv->fbo_array = fbo_array;
  229     priv->block_wcnt = block_wcnt;
  230     priv->block_hcnt = block_hcnt;
  231     return fbo_array[0];
  232 
  233  cleanup:
  234     for (i = 0; i < block_wcnt * block_hcnt; i++)
  235         if (fbo_array[i])
  236             glamor_destroy_fbo(glamor_priv, fbo_array[i]);
  237     free(box_array);
  238     free(fbo_array);
  239     return NULL;
  240 }
  241 
  242 void
  243 glamor_pixmap_clear_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo *fbo)
  244 {
  245     glamor_make_current(glamor_priv);
  246 
  247     assert(fbo->fb != 0 && fbo->tex != 0);
  248 
  249     glamor_set_destination_pixmap_fbo(glamor_priv, fbo, 0, 0, fbo->width, fbo->height);
  250     glClearColor(0.0, 0.0, 0.0, 0.0);
  251     glClear(GL_COLOR_BUFFER_BIT);
  252 }
  253 
  254 glamor_pixmap_fbo *
  255 glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv)
  256 {
  257     glamor_pixmap_fbo *fbo;
  258 
  259     if (pixmap_priv == NULL)
  260         return NULL;
  261 
  262     fbo = pixmap_priv->fbo;
  263     if (fbo == NULL)
  264         return NULL;
  265 
  266     pixmap_priv->fbo = NULL;
  267     return fbo;
  268 }
  269 
  270 /* The pixmap must not be attached to another fbo. */
  271 void
  272 glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo)
  273 {
  274     glamor_pixmap_private *pixmap_priv;
  275 
  276     pixmap_priv = glamor_get_pixmap_private(pixmap);
  277 
  278     if (pixmap_priv->fbo)
  279         return;
  280 
  281     pixmap_priv->fbo = fbo;
  282 
  283     switch (pixmap_priv->type) {
  284     case GLAMOR_TEXTURE_ONLY:
  285     case GLAMOR_TEXTURE_DRM:
  286         pixmap_priv->gl_fbo = GLAMOR_FBO_NORMAL;
  287         pixmap->devPrivate.ptr = NULL;
  288     default:
  289         break;
  290     }
  291 }
  292 
  293 void
  294 glamor_pixmap_destroy_fbo(PixmapPtr pixmap)
  295 {
  296     ScreenPtr screen = pixmap->drawable.pScreen;
  297     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
  298     glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
  299     glamor_pixmap_fbo *fbo;
  300 
  301     if (glamor_pixmap_priv_is_large(priv)) {
  302         int i;
  303 
  304         for (i = 0; i < priv->block_wcnt * priv->block_hcnt; i++)
  305             glamor_destroy_fbo(glamor_priv, priv->fbo_array[i]);
  306         free(priv->fbo_array);
  307         priv->fbo_array = NULL;
  308     }
  309     else {
  310         fbo = glamor_pixmap_detach_fbo(priv);
  311         if (fbo)
  312             glamor_destroy_fbo(glamor_priv, fbo);
  313     }
  314 }
  315 
  316 Bool
  317 glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag)
  318 {
  319     glamor_screen_private *glamor_priv;
  320     glamor_pixmap_private *pixmap_priv;
  321     glamor_pixmap_fbo *fbo;
  322 
  323     glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
  324     pixmap_priv = glamor_get_pixmap_private(pixmap);
  325     if (pixmap_priv->fbo == NULL) {
  326 
  327         fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
  328                                 pixmap->drawable.height, format, flag);
  329         if (fbo == NULL)
  330             return FALSE;
  331 
  332         glamor_pixmap_attach_fbo(pixmap, fbo);
  333     }
  334     else {
  335         /* We do have a fbo, but it may lack of fb or tex. */
  336         if (!pixmap_priv->fbo->tex)
  337             pixmap_priv->fbo->tex =
  338                 _glamor_create_tex(glamor_priv, pixmap->drawable.width,
  339                                    pixmap->drawable.height, format);
  340 
  341         if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->fbo->fb == 0)
  342             if (glamor_pixmap_ensure_fb(glamor_priv, pixmap_priv->fbo) != 0)
  343                 return FALSE;
  344     }
  345 
  346     return TRUE;
  347 }
  348 
  349 _X_EXPORT void
  350 glamor_pixmap_exchange_fbos(PixmapPtr front, PixmapPtr back)
  351 {
  352     glamor_pixmap_private *front_priv, *back_priv;
  353     glamor_pixmap_fbo *temp_fbo;
  354 
  355     front_priv = glamor_get_pixmap_private(front);
  356     back_priv = glamor_get_pixmap_private(back);
  357     temp_fbo = front_priv->fbo;
  358     front_priv->fbo = back_priv->fbo;
  359     back_priv->fbo = temp_fbo;
  360 }