Home | History | Annotate | Download | only in util
      1 /**************************************************************************
      2  *
      3  * Copyright 2009-2010 VMware, Inc.  All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sub license, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial portions
     15  * of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     20  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  **************************************************************************/
     26 
     27 /**
     28  * @file
     29  * Framebuffer utility functions.
     30  *
     31  * @author Brian Paul
     32  */
     33 
     34 
     35 #include "pipe/p_screen.h"
     36 #include "pipe/p_state.h"
     37 #include "pipe/p_defines.h"
     38 #include "util/u_inlines.h"
     39 
     40 #include "util/u_memory.h"
     41 #include "util/u_framebuffer.h"
     42 
     43 
     44 /**
     45  * Compare pipe_framebuffer_state objects.
     46  * \return TRUE if same, FALSE if different
     47  */
     48 boolean
     49 util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
     50                              const struct pipe_framebuffer_state *src)
     51 {
     52    unsigned i;
     53 
     54    if (dst->width != src->width ||
     55        dst->height != src->height)
     56       return FALSE;
     57 
     58    if (dst->samples != src->samples ||
     59        dst->layers  != src->layers)
     60       return FALSE;
     61 
     62    if (dst->nr_cbufs != src->nr_cbufs) {
     63       return FALSE;
     64    }
     65 
     66    for (i = 0; i < src->nr_cbufs; i++) {
     67       if (dst->cbufs[i] != src->cbufs[i]) {
     68          return FALSE;
     69       }
     70    }
     71 
     72    if (dst->zsbuf != src->zsbuf) {
     73       return FALSE;
     74    }
     75 
     76    return TRUE;
     77 }
     78 
     79 
     80 /**
     81  * Copy framebuffer state from src to dst, updating refcounts.
     82  */
     83 void
     84 util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
     85                             const struct pipe_framebuffer_state *src)
     86 {
     87    unsigned i;
     88 
     89    if (src) {
     90       dst->width = src->width;
     91       dst->height = src->height;
     92 
     93       dst->samples = src->samples;
     94       dst->layers  = src->layers;
     95 
     96       for (i = 0; i < src->nr_cbufs; i++)
     97          pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
     98 
     99       /* Set remaining dest cbuf pointers to NULL */
    100       for ( ; i < ARRAY_SIZE(dst->cbufs); i++)
    101          pipe_surface_reference(&dst->cbufs[i], NULL);
    102 
    103       dst->nr_cbufs = src->nr_cbufs;
    104 
    105       pipe_surface_reference(&dst->zsbuf, src->zsbuf);
    106    } else {
    107       dst->width = 0;
    108       dst->height = 0;
    109 
    110       dst->samples = 0;
    111       dst->layers  = 0;
    112 
    113       for (i = 0 ; i < ARRAY_SIZE(dst->cbufs); i++)
    114          pipe_surface_reference(&dst->cbufs[i], NULL);
    115 
    116       dst->nr_cbufs = 0;
    117 
    118       pipe_surface_reference(&dst->zsbuf, NULL);
    119    }
    120 }
    121 
    122 
    123 void
    124 util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb)
    125 {
    126    unsigned i;
    127 
    128    for (i = 0; i < fb->nr_cbufs; i++) {
    129       pipe_surface_reference(&fb->cbufs[i], NULL);
    130    }
    131 
    132    pipe_surface_reference(&fb->zsbuf, NULL);
    133 
    134    fb->samples = fb->layers = 0;
    135    fb->width = fb->height = 0;
    136    fb->nr_cbufs = 0;
    137 }
    138 
    139 
    140 /* Where multiple sizes are allowed for framebuffer surfaces, find the
    141  * minimum width and height of all bound surfaces.
    142  */
    143 boolean
    144 util_framebuffer_min_size(const struct pipe_framebuffer_state *fb,
    145                           unsigned *width,
    146                           unsigned *height)
    147 {
    148    unsigned w = ~0;
    149    unsigned h = ~0;
    150    unsigned i;
    151 
    152    for (i = 0; i < fb->nr_cbufs; i++) {
    153       if (!fb->cbufs[i])
    154          continue;
    155 
    156       w = MIN2(w, fb->cbufs[i]->width);
    157       h = MIN2(h, fb->cbufs[i]->height);
    158    }
    159 
    160    if (fb->zsbuf) {
    161       w = MIN2(w, fb->zsbuf->width);
    162       h = MIN2(h, fb->zsbuf->height);
    163    }
    164 
    165    if (w == ~0u) {
    166       *width = 0;
    167       *height = 0;
    168       return FALSE;
    169    }
    170    else {
    171       *width = w;
    172       *height = h;
    173       return TRUE;
    174    }
    175 }
    176 
    177 
    178 /**
    179  * Return the number of layers set in the framebuffer state.
    180  */
    181 unsigned
    182 util_framebuffer_get_num_layers(const struct pipe_framebuffer_state *fb)
    183 {
    184 	unsigned i, num_layers = 0;
    185 
    186 	/**
    187 	 * In the case of ARB_framebuffer_no_attachment
    188 	 * we obtain the number of layers directly from
    189 	 * the framebuffer state.
    190 	 */
    191 	if (!(fb->nr_cbufs || fb->zsbuf))
    192 		return fb->layers;
    193 
    194 	for (i = 0; i < fb->nr_cbufs; i++) {
    195 		if (fb->cbufs[i]) {
    196 			unsigned num = fb->cbufs[i]->u.tex.last_layer -
    197 				       fb->cbufs[i]->u.tex.first_layer + 1;
    198 			num_layers = MAX2(num_layers, num);
    199 		}
    200 	}
    201 	if (fb->zsbuf) {
    202 		unsigned num = fb->zsbuf->u.tex.last_layer -
    203 			       fb->zsbuf->u.tex.first_layer + 1;
    204 		num_layers = MAX2(num_layers, num);
    205 	}
    206 	return num_layers;
    207 }
    208 
    209 
    210 /**
    211  * Return the number of MSAA samples.
    212  */
    213 unsigned
    214 util_framebuffer_get_num_samples(const struct pipe_framebuffer_state *fb)
    215 {
    216    unsigned i;
    217 
    218    /**
    219     * In the case of ARB_framebuffer_no_attachment
    220     * we obtain the number of samples directly from
    221     * the framebuffer state.
    222     *
    223     * NOTE: fb->samples may wind up as zero due to memset()'s on internal
    224     *       driver structures on their initialization and so we take the
    225     *       MAX here to ensure we have a valid number of samples. However,
    226     *       if samples is legitimately not getting set somewhere
    227     *       multi-sampling will evidently break.
    228     */
    229    if (!(fb->nr_cbufs || fb->zsbuf))
    230       return MAX2(fb->samples, 1);
    231 
    232    for (i = 0; i < fb->nr_cbufs; i++) {
    233       if (fb->cbufs[i]) {
    234          return MAX2(1, fb->cbufs[i]->texture->nr_samples);
    235       }
    236    }
    237    if (fb->zsbuf) {
    238       return MAX2(1, fb->zsbuf->texture->nr_samples);
    239    }
    240 
    241    return 1;
    242 }
    243