Path: blob/21.2-virgl/src/gallium/auxiliary/util/u_framebuffer.c
4561 views
/**************************************************************************1*2* Copyright 2009-2010 VMware, Inc. All Rights Reserved.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the6* "Software"), to deal in the Software without restriction, including7* without limitation the rights to use, copy, modify, merge, publish,8* distribute, sub license, and/or sell copies of the Software, and to9* permit persons to whom the Software is furnished to do so, subject to10* the following conditions:11*12* The above copyright notice and this permission notice (including the13* next paragraph) shall be included in all copies or substantial portions14* of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS17* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.19* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR20* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,21* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE22* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.23*24**************************************************************************/2526/**27* @file28* Framebuffer utility functions.29*30* @author Brian Paul31*/323334#include "pipe/p_screen.h"35#include "pipe/p_state.h"36#include "pipe/p_defines.h"37#include "util/u_inlines.h"3839#include "util/u_memory.h"40#include "util/u_framebuffer.h"414243/**44* Compare pipe_framebuffer_state objects.45* \return TRUE if same, FALSE if different46*/47boolean48util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,49const struct pipe_framebuffer_state *src)50{51unsigned i;5253if (dst->width != src->width ||54dst->height != src->height)55return FALSE;5657if (dst->samples != src->samples ||58dst->layers != src->layers)59return FALSE;6061if (dst->nr_cbufs != src->nr_cbufs) {62return FALSE;63}6465for (i = 0; i < src->nr_cbufs; i++) {66if (dst->cbufs[i] != src->cbufs[i]) {67return FALSE;68}69}7071if (dst->zsbuf != src->zsbuf) {72return FALSE;73}7475return TRUE;76}777879/**80* Copy framebuffer state from src to dst, updating refcounts.81*/82void83util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,84const struct pipe_framebuffer_state *src)85{86unsigned i;8788if (src) {89dst->width = src->width;90dst->height = src->height;9192dst->samples = src->samples;93dst->layers = src->layers;9495for (i = 0; i < src->nr_cbufs; i++)96pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);9798/* Set remaining dest cbuf pointers to NULL */99for ( ; i < ARRAY_SIZE(dst->cbufs); i++)100pipe_surface_reference(&dst->cbufs[i], NULL);101102dst->nr_cbufs = src->nr_cbufs;103104pipe_surface_reference(&dst->zsbuf, src->zsbuf);105} else {106dst->width = 0;107dst->height = 0;108109dst->samples = 0;110dst->layers = 0;111112for (i = 0 ; i < ARRAY_SIZE(dst->cbufs); i++)113pipe_surface_reference(&dst->cbufs[i], NULL);114115dst->nr_cbufs = 0;116117pipe_surface_reference(&dst->zsbuf, NULL);118}119}120121122void123util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb)124{125unsigned i;126127for (i = 0; i < fb->nr_cbufs; i++) {128pipe_surface_reference(&fb->cbufs[i], NULL);129}130131pipe_surface_reference(&fb->zsbuf, NULL);132133fb->samples = fb->layers = 0;134fb->width = fb->height = 0;135fb->nr_cbufs = 0;136}137138139/* Where multiple sizes are allowed for framebuffer surfaces, find the140* minimum width and height of all bound surfaces.141*/142boolean143util_framebuffer_min_size(const struct pipe_framebuffer_state *fb,144unsigned *width,145unsigned *height)146{147unsigned w = ~0;148unsigned h = ~0;149unsigned i;150151for (i = 0; i < fb->nr_cbufs; i++) {152if (!fb->cbufs[i])153continue;154155w = MIN2(w, fb->cbufs[i]->width);156h = MIN2(h, fb->cbufs[i]->height);157}158159if (fb->zsbuf) {160w = MIN2(w, fb->zsbuf->width);161h = MIN2(h, fb->zsbuf->height);162}163164if (w == ~0u) {165*width = 0;166*height = 0;167return FALSE;168}169else {170*width = w;171*height = h;172return TRUE;173}174}175176177/**178* Return the number of layers set in the framebuffer state.179*/180unsigned181util_framebuffer_get_num_layers(const struct pipe_framebuffer_state *fb)182{183unsigned i, num_layers = 0;184185/**186* In the case of ARB_framebuffer_no_attachment187* we obtain the number of layers directly from188* the framebuffer state.189*/190if (!(fb->nr_cbufs || fb->zsbuf))191return fb->layers;192193for (i = 0; i < fb->nr_cbufs; i++) {194if (fb->cbufs[i]) {195unsigned num = fb->cbufs[i]->u.tex.last_layer -196fb->cbufs[i]->u.tex.first_layer + 1;197num_layers = MAX2(num_layers, num);198}199}200if (fb->zsbuf) {201unsigned num = fb->zsbuf->u.tex.last_layer -202fb->zsbuf->u.tex.first_layer + 1;203num_layers = MAX2(num_layers, num);204}205return num_layers;206}207208209/**210* Return the number of MSAA samples.211*/212unsigned213util_framebuffer_get_num_samples(const struct pipe_framebuffer_state *fb)214{215unsigned i;216217/**218* In the case of ARB_framebuffer_no_attachment219* we obtain the number of samples directly from220* the framebuffer state.221*222* NOTE: fb->samples may wind up as zero due to memset()'s on internal223* driver structures on their initialization and so we take the224* MAX here to ensure we have a valid number of samples. However,225* if samples is legitimately not getting set somewhere226* multi-sampling will evidently break.227*/228if (!(fb->nr_cbufs || fb->zsbuf))229return MAX2(fb->samples, 1);230231/**232* If a driver doesn't advertise PIPE_CAP_SURFACE_SAMPLE_COUNT,233* pipe_surface::nr_samples will always be 0.234*/235for (i = 0; i < fb->nr_cbufs; i++) {236if (fb->cbufs[i]) {237return MAX3(1, fb->cbufs[i]->texture->nr_samples,238fb->cbufs[i]->nr_samples);239}240}241if (fb->zsbuf) {242return MAX3(1, fb->zsbuf->texture->nr_samples,243fb->zsbuf->nr_samples);244}245246return MAX2(fb->samples, 1);247}248249250/**251* Flip the sample location state along the Y axis.252*/253void254util_sample_locations_flip_y(struct pipe_screen *screen, unsigned fb_height,255unsigned samples, uint8_t *locations)256{257unsigned row, i, shift, grid_width, grid_height;258uint8_t new_locations[259PIPE_MAX_SAMPLE_LOCATION_GRID_SIZE *260PIPE_MAX_SAMPLE_LOCATION_GRID_SIZE * 32];261262screen->get_sample_pixel_grid(screen, samples, &grid_width, &grid_height);263264shift = fb_height % grid_height;265266for (row = 0; row < grid_height; row++) {267unsigned row_size = grid_width * samples;268for (i = 0; i < row_size; i++) {269unsigned dest_row = grid_height - row - 1;270/* this relies on unsigned integer wraparound behaviour */271dest_row = (dest_row - shift) % grid_height;272new_locations[dest_row * row_size + i] = locations[row * row_size + i];273}274}275276memcpy(locations, new_locations, grid_width * grid_height * samples);277}278279280