Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/auxiliary/util/u_framebuffer.c
4561 views
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
/**
233
* If a driver doesn't advertise PIPE_CAP_SURFACE_SAMPLE_COUNT,
234
* pipe_surface::nr_samples will always be 0.
235
*/
236
for (i = 0; i < fb->nr_cbufs; i++) {
237
if (fb->cbufs[i]) {
238
return MAX3(1, fb->cbufs[i]->texture->nr_samples,
239
fb->cbufs[i]->nr_samples);
240
}
241
}
242
if (fb->zsbuf) {
243
return MAX3(1, fb->zsbuf->texture->nr_samples,
244
fb->zsbuf->nr_samples);
245
}
246
247
return MAX2(fb->samples, 1);
248
}
249
250
251
/**
252
* Flip the sample location state along the Y axis.
253
*/
254
void
255
util_sample_locations_flip_y(struct pipe_screen *screen, unsigned fb_height,
256
unsigned samples, uint8_t *locations)
257
{
258
unsigned row, i, shift, grid_width, grid_height;
259
uint8_t new_locations[
260
PIPE_MAX_SAMPLE_LOCATION_GRID_SIZE *
261
PIPE_MAX_SAMPLE_LOCATION_GRID_SIZE * 32];
262
263
screen->get_sample_pixel_grid(screen, samples, &grid_width, &grid_height);
264
265
shift = fb_height % grid_height;
266
267
for (row = 0; row < grid_height; row++) {
268
unsigned row_size = grid_width * samples;
269
for (i = 0; i < row_size; i++) {
270
unsigned dest_row = grid_height - row - 1;
271
/* this relies on unsigned integer wraparound behaviour */
272
dest_row = (dest_row - shift) % grid_height;
273
new_locations[dest_row * row_size + i] = locations[row * row_size + i];
274
}
275
}
276
277
memcpy(locations, new_locations, grid_width * grid_height * samples);
278
}
279
280