xref: /aosp_15_r20/external/mesa3d/src/mesa/main/renderbuffer.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*61046927SAndroid Build Coastguard Worker  *
13*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
14*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
15*61046927SAndroid Build Coastguard Worker  *
16*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
23*61046927SAndroid Build Coastguard Worker  */
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker #include "context.h"
29*61046927SAndroid Build Coastguard Worker #include "bufferobj.h"
30*61046927SAndroid Build Coastguard Worker #include "fbobject.h"
31*61046927SAndroid Build Coastguard Worker #include "formats.h"
32*61046927SAndroid Build Coastguard Worker #include "glformats.h"
33*61046927SAndroid Build Coastguard Worker #include "mtypes.h"
34*61046927SAndroid Build Coastguard Worker #include "renderbuffer.h"
35*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
36*61046927SAndroid Build Coastguard Worker #include "util/u_inlines.h"
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_context.h"
39*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_format.h"
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker /**
42*61046927SAndroid Build Coastguard Worker  * Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces.
43*61046927SAndroid Build Coastguard Worker  */
44*61046927SAndroid Build Coastguard Worker static enum pipe_format
choose_renderbuffer_format(struct gl_context * ctx,GLenum internalFormat,unsigned sample_count,unsigned storage_sample_count)45*61046927SAndroid Build Coastguard Worker choose_renderbuffer_format(struct gl_context *ctx,
46*61046927SAndroid Build Coastguard Worker                            GLenum internalFormat, unsigned sample_count,
47*61046927SAndroid Build Coastguard Worker                            unsigned storage_sample_count)
48*61046927SAndroid Build Coastguard Worker {
49*61046927SAndroid Build Coastguard Worker    unsigned bindings;
50*61046927SAndroid Build Coastguard Worker    if (_mesa_is_depth_or_stencil_format(internalFormat))
51*61046927SAndroid Build Coastguard Worker       bindings = PIPE_BIND_DEPTH_STENCIL;
52*61046927SAndroid Build Coastguard Worker    else
53*61046927SAndroid Build Coastguard Worker       bindings = PIPE_BIND_RENDER_TARGET;
54*61046927SAndroid Build Coastguard Worker    return st_choose_format(st_context(ctx), internalFormat, GL_NONE, GL_NONE,
55*61046927SAndroid Build Coastguard Worker                            PIPE_TEXTURE_2D, sample_count,
56*61046927SAndroid Build Coastguard Worker                            storage_sample_count, bindings,
57*61046927SAndroid Build Coastguard Worker                            false, false);
58*61046927SAndroid Build Coastguard Worker }
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker /**
63*61046927SAndroid Build Coastguard Worker  * Delete a gl_framebuffer.
64*61046927SAndroid Build Coastguard Worker  * This is the default function for renderbuffer->Delete().
65*61046927SAndroid Build Coastguard Worker  * Drivers which subclass gl_renderbuffer should probably implement their
66*61046927SAndroid Build Coastguard Worker  * own delete function.  But the driver might also call this function to
67*61046927SAndroid Build Coastguard Worker  * free the object in the end.
68*61046927SAndroid Build Coastguard Worker  */
69*61046927SAndroid Build Coastguard Worker static void
delete_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)70*61046927SAndroid Build Coastguard Worker delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
71*61046927SAndroid Build Coastguard Worker {
72*61046927SAndroid Build Coastguard Worker    if (ctx) {
73*61046927SAndroid Build Coastguard Worker       pipe_surface_release(ctx->pipe, &rb->surface_srgb);
74*61046927SAndroid Build Coastguard Worker       pipe_surface_release(ctx->pipe, &rb->surface_linear);
75*61046927SAndroid Build Coastguard Worker    } else {
76*61046927SAndroid Build Coastguard Worker       pipe_surface_release_no_context(&rb->surface_srgb);
77*61046927SAndroid Build Coastguard Worker       pipe_surface_release_no_context(&rb->surface_linear);
78*61046927SAndroid Build Coastguard Worker    }
79*61046927SAndroid Build Coastguard Worker    rb->surface = NULL;
80*61046927SAndroid Build Coastguard Worker    pipe_resource_reference(&rb->texture, NULL);
81*61046927SAndroid Build Coastguard Worker    free(rb->data);
82*61046927SAndroid Build Coastguard Worker    free(rb->Label);
83*61046927SAndroid Build Coastguard Worker    free(rb);
84*61046927SAndroid Build Coastguard Worker }
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker static GLboolean
renderbuffer_alloc_sw_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)87*61046927SAndroid Build Coastguard Worker renderbuffer_alloc_sw_storage(struct gl_context *ctx,
88*61046927SAndroid Build Coastguard Worker                               struct gl_renderbuffer *rb,
89*61046927SAndroid Build Coastguard Worker                               GLenum internalFormat,
90*61046927SAndroid Build Coastguard Worker                               GLuint width, GLuint height)
91*61046927SAndroid Build Coastguard Worker {
92*61046927SAndroid Build Coastguard Worker    enum pipe_format format;
93*61046927SAndroid Build Coastguard Worker    size_t size;
94*61046927SAndroid Build Coastguard Worker 
95*61046927SAndroid Build Coastguard Worker    free(rb->data);
96*61046927SAndroid Build Coastguard Worker    rb->data = NULL;
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker    if (internalFormat == GL_RGBA16_SNORM) {
99*61046927SAndroid Build Coastguard Worker       /* Special case for software accum buffers.  Otherwise, if the
100*61046927SAndroid Build Coastguard Worker        * call to choose_renderbuffer_format() fails (because the
101*61046927SAndroid Build Coastguard Worker        * driver doesn't support signed 16-bit/channel colors) we'd
102*61046927SAndroid Build Coastguard Worker        * just return without allocating the software accum buffer.
103*61046927SAndroid Build Coastguard Worker        */
104*61046927SAndroid Build Coastguard Worker       format = PIPE_FORMAT_R16G16B16A16_SNORM;
105*61046927SAndroid Build Coastguard Worker    }
106*61046927SAndroid Build Coastguard Worker    else {
107*61046927SAndroid Build Coastguard Worker       format = choose_renderbuffer_format(ctx, internalFormat, 0, 0);
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker       /* Not setting gl_renderbuffer::Format here will cause
110*61046927SAndroid Build Coastguard Worker        * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
111*61046927SAndroid Build Coastguard Worker        */
112*61046927SAndroid Build Coastguard Worker       if (format == PIPE_FORMAT_NONE) {
113*61046927SAndroid Build Coastguard Worker          return GL_TRUE;
114*61046927SAndroid Build Coastguard Worker       }
115*61046927SAndroid Build Coastguard Worker    }
116*61046927SAndroid Build Coastguard Worker 
117*61046927SAndroid Build Coastguard Worker    rb->Format = st_pipe_format_to_mesa_format(format);
118*61046927SAndroid Build Coastguard Worker 
119*61046927SAndroid Build Coastguard Worker    size = _mesa_format_image_size(rb->Format, width, height, 1);
120*61046927SAndroid Build Coastguard Worker    rb->data = malloc(size);
121*61046927SAndroid Build Coastguard Worker    return rb->data != NULL;
122*61046927SAndroid Build Coastguard Worker }
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker /**
126*61046927SAndroid Build Coastguard Worker  * gl_renderbuffer::AllocStorage()
127*61046927SAndroid Build Coastguard Worker  * This is called to allocate the original drawing surface, and
128*61046927SAndroid Build Coastguard Worker  * during window resize.
129*61046927SAndroid Build Coastguard Worker  */
130*61046927SAndroid Build Coastguard Worker static GLboolean
renderbuffer_alloc_storage(struct gl_context * ctx,struct gl_renderbuffer * rb,GLenum internalFormat,GLuint width,GLuint height)131*61046927SAndroid Build Coastguard Worker renderbuffer_alloc_storage(struct gl_context * ctx,
132*61046927SAndroid Build Coastguard Worker                            struct gl_renderbuffer *rb,
133*61046927SAndroid Build Coastguard Worker                            GLenum internalFormat,
134*61046927SAndroid Build Coastguard Worker                            GLuint width, GLuint height)
135*61046927SAndroid Build Coastguard Worker {
136*61046927SAndroid Build Coastguard Worker    struct st_context *st = st_context(ctx);
137*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen = ctx->screen;
138*61046927SAndroid Build Coastguard Worker    enum pipe_format format = PIPE_FORMAT_NONE;
139*61046927SAndroid Build Coastguard Worker    struct pipe_resource templ;
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker    /* init renderbuffer fields */
142*61046927SAndroid Build Coastguard Worker    rb->Width  = width;
143*61046927SAndroid Build Coastguard Worker    rb->Height = height;
144*61046927SAndroid Build Coastguard Worker    rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
145*61046927SAndroid Build Coastguard Worker    rb->defined = GL_FALSE;  /* undefined contents now */
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker    if (rb->software) {
148*61046927SAndroid Build Coastguard Worker       return renderbuffer_alloc_sw_storage(ctx, rb, internalFormat,
149*61046927SAndroid Build Coastguard Worker                                            width, height);
150*61046927SAndroid Build Coastguard Worker    }
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker    /* Free the old surface and texture
153*61046927SAndroid Build Coastguard Worker     */
154*61046927SAndroid Build Coastguard Worker    pipe_surface_reference(&rb->surface_srgb, NULL);
155*61046927SAndroid Build Coastguard Worker    pipe_surface_reference(&rb->surface_linear, NULL);
156*61046927SAndroid Build Coastguard Worker    rb->surface = NULL;
157*61046927SAndroid Build Coastguard Worker    pipe_resource_reference(&rb->texture, NULL);
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker    /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
160*61046927SAndroid Build Coastguard Worker     * formats.
161*61046927SAndroid Build Coastguard Worker     */
162*61046927SAndroid Build Coastguard Worker    if (!ctx->Extensions.EXT_sRGB) {
163*61046927SAndroid Build Coastguard Worker       internalFormat = _mesa_get_linear_internalformat(internalFormat);
164*61046927SAndroid Build Coastguard Worker    }
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    /* Handle multisample renderbuffers first.
167*61046927SAndroid Build Coastguard Worker     *
168*61046927SAndroid Build Coastguard Worker     * From ARB_framebuffer_object:
169*61046927SAndroid Build Coastguard Worker     *   If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero.
170*61046927SAndroid Build Coastguard Worker     *   Otherwise <samples> represents a request for a desired minimum
171*61046927SAndroid Build Coastguard Worker     *   number of samples. Since different implementations may support
172*61046927SAndroid Build Coastguard Worker     *   different sample counts for multisampled rendering, the actual
173*61046927SAndroid Build Coastguard Worker     *   number of samples allocated for the renderbuffer image is
174*61046927SAndroid Build Coastguard Worker     *   implementation dependent.  However, the resulting value for
175*61046927SAndroid Build Coastguard Worker     *   RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal
176*61046927SAndroid Build Coastguard Worker     *   to <samples> and no more than the next larger sample count supported
177*61046927SAndroid Build Coastguard Worker     *   by the implementation.
178*61046927SAndroid Build Coastguard Worker     *
179*61046927SAndroid Build Coastguard Worker     * Find the supported number of samples >= rb->NumSamples
180*61046927SAndroid Build Coastguard Worker     */
181*61046927SAndroid Build Coastguard Worker    if (rb->NumSamples > 0) {
182*61046927SAndroid Build Coastguard Worker       unsigned start, start_storage;
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker       if (ctx->Const.MaxSamples > 1 &&  rb->NumSamples == 1) {
185*61046927SAndroid Build Coastguard Worker          /* don't try num_samples = 1 with drivers that support real msaa */
186*61046927SAndroid Build Coastguard Worker          start = 2;
187*61046927SAndroid Build Coastguard Worker          start_storage = 2;
188*61046927SAndroid Build Coastguard Worker       } else {
189*61046927SAndroid Build Coastguard Worker          start = rb->NumSamples;
190*61046927SAndroid Build Coastguard Worker          start_storage = rb->NumStorageSamples;
191*61046927SAndroid Build Coastguard Worker       }
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker       if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
194*61046927SAndroid Build Coastguard Worker          if (rb->_BaseFormat == GL_DEPTH_COMPONENT ||
195*61046927SAndroid Build Coastguard Worker              rb->_BaseFormat == GL_DEPTH_STENCIL ||
196*61046927SAndroid Build Coastguard Worker              rb->_BaseFormat == GL_STENCIL_INDEX) {
197*61046927SAndroid Build Coastguard Worker             /* Find a supported depth-stencil format. */
198*61046927SAndroid Build Coastguard Worker             for (unsigned samples = start;
199*61046927SAndroid Build Coastguard Worker                  samples <= ctx->Const.MaxDepthStencilFramebufferSamples;
200*61046927SAndroid Build Coastguard Worker                  samples++) {
201*61046927SAndroid Build Coastguard Worker                format = choose_renderbuffer_format(ctx, internalFormat,
202*61046927SAndroid Build Coastguard Worker                                                    samples, samples);
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker                if (format != PIPE_FORMAT_NONE) {
205*61046927SAndroid Build Coastguard Worker                   rb->NumSamples = samples;
206*61046927SAndroid Build Coastguard Worker                   rb->NumStorageSamples = samples;
207*61046927SAndroid Build Coastguard Worker                   break;
208*61046927SAndroid Build Coastguard Worker                }
209*61046927SAndroid Build Coastguard Worker             }
210*61046927SAndroid Build Coastguard Worker          } else {
211*61046927SAndroid Build Coastguard Worker             /* Find a supported color format, samples >= storage_samples. */
212*61046927SAndroid Build Coastguard Worker             for (unsigned storage_samples = start_storage;
213*61046927SAndroid Build Coastguard Worker                  storage_samples <= ctx->Const.MaxColorFramebufferStorageSamples;
214*61046927SAndroid Build Coastguard Worker                  storage_samples++) {
215*61046927SAndroid Build Coastguard Worker                for (unsigned samples = MAX2(start, storage_samples);
216*61046927SAndroid Build Coastguard Worker                     samples <= ctx->Const.MaxColorFramebufferSamples;
217*61046927SAndroid Build Coastguard Worker                     samples++) {
218*61046927SAndroid Build Coastguard Worker                   format = choose_renderbuffer_format(ctx, internalFormat,
219*61046927SAndroid Build Coastguard Worker                                                       samples,
220*61046927SAndroid Build Coastguard Worker                                                       storage_samples);
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker                   if (format != PIPE_FORMAT_NONE) {
223*61046927SAndroid Build Coastguard Worker                      rb->NumSamples = samples;
224*61046927SAndroid Build Coastguard Worker                      rb->NumStorageSamples = storage_samples;
225*61046927SAndroid Build Coastguard Worker                      goto found;
226*61046927SAndroid Build Coastguard Worker                   }
227*61046927SAndroid Build Coastguard Worker                }
228*61046927SAndroid Build Coastguard Worker             }
229*61046927SAndroid Build Coastguard Worker             found:;
230*61046927SAndroid Build Coastguard Worker          }
231*61046927SAndroid Build Coastguard Worker       } else {
232*61046927SAndroid Build Coastguard Worker          for (unsigned samples = start; samples <= ctx->Const.MaxSamples;
233*61046927SAndroid Build Coastguard Worker               samples++) {
234*61046927SAndroid Build Coastguard Worker             format = choose_renderbuffer_format(ctx, internalFormat,
235*61046927SAndroid Build Coastguard Worker                                                 samples, samples);
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker             if (format != PIPE_FORMAT_NONE) {
238*61046927SAndroid Build Coastguard Worker                rb->NumSamples = samples;
239*61046927SAndroid Build Coastguard Worker                rb->NumStorageSamples = samples;
240*61046927SAndroid Build Coastguard Worker                break;
241*61046927SAndroid Build Coastguard Worker             }
242*61046927SAndroid Build Coastguard Worker          }
243*61046927SAndroid Build Coastguard Worker       }
244*61046927SAndroid Build Coastguard Worker    } else {
245*61046927SAndroid Build Coastguard Worker       format = choose_renderbuffer_format(ctx, internalFormat, 0, 0);
246*61046927SAndroid Build Coastguard Worker    }
247*61046927SAndroid Build Coastguard Worker 
248*61046927SAndroid Build Coastguard Worker    /* Not setting gl_renderbuffer::Format here will cause
249*61046927SAndroid Build Coastguard Worker     * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
250*61046927SAndroid Build Coastguard Worker     */
251*61046927SAndroid Build Coastguard Worker    if (format == PIPE_FORMAT_NONE) {
252*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
253*61046927SAndroid Build Coastguard Worker    }
254*61046927SAndroid Build Coastguard Worker 
255*61046927SAndroid Build Coastguard Worker    rb->Format = st_pipe_format_to_mesa_format(format);
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker    if (width == 0 || height == 0) {
258*61046927SAndroid Build Coastguard Worker       /* if size is zero, nothing to allocate */
259*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
260*61046927SAndroid Build Coastguard Worker    }
261*61046927SAndroid Build Coastguard Worker 
262*61046927SAndroid Build Coastguard Worker    /* Setup new texture template.
263*61046927SAndroid Build Coastguard Worker     */
264*61046927SAndroid Build Coastguard Worker    memset(&templ, 0, sizeof(templ));
265*61046927SAndroid Build Coastguard Worker    templ.target = st->internal_target;
266*61046927SAndroid Build Coastguard Worker    templ.format = format;
267*61046927SAndroid Build Coastguard Worker    templ.width0 = width;
268*61046927SAndroid Build Coastguard Worker    templ.height0 = height;
269*61046927SAndroid Build Coastguard Worker    templ.depth0 = 1;
270*61046927SAndroid Build Coastguard Worker    templ.array_size = 1;
271*61046927SAndroid Build Coastguard Worker    templ.nr_samples = rb->NumSamples;
272*61046927SAndroid Build Coastguard Worker    templ.nr_storage_samples = rb->NumStorageSamples;
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker    if (util_format_is_depth_or_stencil(format)) {
275*61046927SAndroid Build Coastguard Worker       templ.bind = PIPE_BIND_DEPTH_STENCIL;
276*61046927SAndroid Build Coastguard Worker    }
277*61046927SAndroid Build Coastguard Worker    else if (rb->Name != 0) {
278*61046927SAndroid Build Coastguard Worker       /* this is a user-created renderbuffer */
279*61046927SAndroid Build Coastguard Worker       templ.bind = PIPE_BIND_RENDER_TARGET;
280*61046927SAndroid Build Coastguard Worker    }
281*61046927SAndroid Build Coastguard Worker    else {
282*61046927SAndroid Build Coastguard Worker       /* this is a window-system buffer */
283*61046927SAndroid Build Coastguard Worker       templ.bind = (PIPE_BIND_DISPLAY_TARGET |
284*61046927SAndroid Build Coastguard Worker                     PIPE_BIND_RENDER_TARGET);
285*61046927SAndroid Build Coastguard Worker    }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker    rb->texture = screen->resource_create(screen, &templ);
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    if (!rb->texture)
290*61046927SAndroid Build Coastguard Worker       return false;
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker    _mesa_update_renderbuffer_surface(ctx, rb);
293*61046927SAndroid Build Coastguard Worker    return rb->surface != NULL;
294*61046927SAndroid Build Coastguard Worker }
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker /**
297*61046927SAndroid Build Coastguard Worker  * Initialize the fields of a gl_renderbuffer to default values.
298*61046927SAndroid Build Coastguard Worker  */
299*61046927SAndroid Build Coastguard Worker void
_mesa_init_renderbuffer(struct gl_renderbuffer * rb,GLuint name)300*61046927SAndroid Build Coastguard Worker _mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
301*61046927SAndroid Build Coastguard Worker {
302*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    rb->Name = name;
305*61046927SAndroid Build Coastguard Worker    rb->RefCount = 1;
306*61046927SAndroid Build Coastguard Worker    rb->Delete = delete_renderbuffer;
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    /* The rest of these should be set later by the caller of this function or
309*61046927SAndroid Build Coastguard Worker     * the AllocStorage method:
310*61046927SAndroid Build Coastguard Worker     */
311*61046927SAndroid Build Coastguard Worker    rb->AllocStorage = NULL;
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker    rb->Width = 0;
314*61046927SAndroid Build Coastguard Worker    rb->Height = 0;
315*61046927SAndroid Build Coastguard Worker    rb->Depth = 0;
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker    /* In GL 3, the initial format is GL_RGBA according to Table 6.26
318*61046927SAndroid Build Coastguard Worker     * on page 302 of the GL 3.3 spec.
319*61046927SAndroid Build Coastguard Worker     *
320*61046927SAndroid Build Coastguard Worker     * In GLES 3, the initial format is GL_RGBA4 according to Table 6.15
321*61046927SAndroid Build Coastguard Worker     * on page 258 of the GLES 3.0.4 spec.
322*61046927SAndroid Build Coastguard Worker     *
323*61046927SAndroid Build Coastguard Worker     * If the context is current, set the initial format based on the
324*61046927SAndroid Build Coastguard Worker     * specs. If the context is not current, we cannot determine the
325*61046927SAndroid Build Coastguard Worker     * API, so default to GL_RGBA.
326*61046927SAndroid Build Coastguard Worker     */
327*61046927SAndroid Build Coastguard Worker    if (ctx && _mesa_is_gles(ctx)) {
328*61046927SAndroid Build Coastguard Worker       rb->InternalFormat = GL_RGBA4;
329*61046927SAndroid Build Coastguard Worker    } else {
330*61046927SAndroid Build Coastguard Worker       rb->InternalFormat = GL_RGBA;
331*61046927SAndroid Build Coastguard Worker    }
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    rb->Format = MESA_FORMAT_NONE;
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker    rb->AllocStorage = renderbuffer_alloc_storage;
336*61046927SAndroid Build Coastguard Worker }
337*61046927SAndroid Build Coastguard Worker 
338*61046927SAndroid Build Coastguard Worker static void
validate_and_init_renderbuffer_attachment(struct gl_framebuffer * fb,gl_buffer_index bufferName,struct gl_renderbuffer * rb)339*61046927SAndroid Build Coastguard Worker validate_and_init_renderbuffer_attachment(struct gl_framebuffer *fb,
340*61046927SAndroid Build Coastguard Worker                                           gl_buffer_index bufferName,
341*61046927SAndroid Build Coastguard Worker                                           struct gl_renderbuffer *rb)
342*61046927SAndroid Build Coastguard Worker {
343*61046927SAndroid Build Coastguard Worker    assert(fb);
344*61046927SAndroid Build Coastguard Worker    assert(rb);
345*61046927SAndroid Build Coastguard Worker    assert(bufferName < BUFFER_COUNT);
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    /* There should be no previous renderbuffer on this attachment point,
348*61046927SAndroid Build Coastguard Worker     * with the exception of depth/stencil since the same renderbuffer may
349*61046927SAndroid Build Coastguard Worker     * be used for both.
350*61046927SAndroid Build Coastguard Worker     */
351*61046927SAndroid Build Coastguard Worker    assert(bufferName == BUFFER_DEPTH ||
352*61046927SAndroid Build Coastguard Worker           bufferName == BUFFER_STENCIL ||
353*61046927SAndroid Build Coastguard Worker           fb->Attachment[bufferName].Renderbuffer == NULL);
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker    /* winsys vs. user-created buffer cross check */
356*61046927SAndroid Build Coastguard Worker    if (_mesa_is_user_fbo(fb)) {
357*61046927SAndroid Build Coastguard Worker       assert(rb->Name);
358*61046927SAndroid Build Coastguard Worker    }
359*61046927SAndroid Build Coastguard Worker    else {
360*61046927SAndroid Build Coastguard Worker       assert(!rb->Name);
361*61046927SAndroid Build Coastguard Worker    }
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker    fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
364*61046927SAndroid Build Coastguard Worker    fb->Attachment[bufferName].Complete = GL_TRUE;
365*61046927SAndroid Build Coastguard Worker }
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker /**
369*61046927SAndroid Build Coastguard Worker  * Attach a renderbuffer to a framebuffer.
370*61046927SAndroid Build Coastguard Worker  * \param bufferName  one of the BUFFER_x tokens
371*61046927SAndroid Build Coastguard Worker  *
372*61046927SAndroid Build Coastguard Worker  * This function avoids adding a reference and is therefore intended to be
373*61046927SAndroid Build Coastguard Worker  * used with a freshly created renderbuffer.
374*61046927SAndroid Build Coastguard Worker  */
375*61046927SAndroid Build Coastguard Worker void
_mesa_attach_and_own_rb(struct gl_framebuffer * fb,gl_buffer_index bufferName,struct gl_renderbuffer * rb)376*61046927SAndroid Build Coastguard Worker _mesa_attach_and_own_rb(struct gl_framebuffer *fb,
377*61046927SAndroid Build Coastguard Worker                         gl_buffer_index bufferName,
378*61046927SAndroid Build Coastguard Worker                         struct gl_renderbuffer *rb)
379*61046927SAndroid Build Coastguard Worker {
380*61046927SAndroid Build Coastguard Worker    assert(rb->RefCount == 1);
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
385*61046927SAndroid Build Coastguard Worker                                 NULL);
386*61046927SAndroid Build Coastguard Worker    fb->Attachment[bufferName].Renderbuffer = rb;
387*61046927SAndroid Build Coastguard Worker }
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker /**
390*61046927SAndroid Build Coastguard Worker  * Attach a renderbuffer to a framebuffer.
391*61046927SAndroid Build Coastguard Worker  * \param bufferName  one of the BUFFER_x tokens
392*61046927SAndroid Build Coastguard Worker  */
393*61046927SAndroid Build Coastguard Worker void
_mesa_attach_and_reference_rb(struct gl_framebuffer * fb,gl_buffer_index bufferName,struct gl_renderbuffer * rb)394*61046927SAndroid Build Coastguard Worker _mesa_attach_and_reference_rb(struct gl_framebuffer *fb,
395*61046927SAndroid Build Coastguard Worker                               gl_buffer_index bufferName,
396*61046927SAndroid Build Coastguard Worker                               struct gl_renderbuffer *rb)
397*61046927SAndroid Build Coastguard Worker {
398*61046927SAndroid Build Coastguard Worker    validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
399*61046927SAndroid Build Coastguard Worker    _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
400*61046927SAndroid Build Coastguard Worker }
401*61046927SAndroid Build Coastguard Worker 
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker /**
404*61046927SAndroid Build Coastguard Worker  * Remove the named renderbuffer from the given framebuffer.
405*61046927SAndroid Build Coastguard Worker  * \param bufferName  one of the BUFFER_x tokens
406*61046927SAndroid Build Coastguard Worker  */
407*61046927SAndroid Build Coastguard Worker void
_mesa_remove_renderbuffer(struct gl_framebuffer * fb,gl_buffer_index bufferName)408*61046927SAndroid Build Coastguard Worker _mesa_remove_renderbuffer(struct gl_framebuffer *fb,
409*61046927SAndroid Build Coastguard Worker                           gl_buffer_index bufferName)
410*61046927SAndroid Build Coastguard Worker {
411*61046927SAndroid Build Coastguard Worker    assert(bufferName < BUFFER_COUNT);
412*61046927SAndroid Build Coastguard Worker    _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
413*61046927SAndroid Build Coastguard Worker                                 NULL);
414*61046927SAndroid Build Coastguard Worker }
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker /**
418*61046927SAndroid Build Coastguard Worker  * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
419*61046927SAndroid Build Coastguard Worker  * dereference that buffer first.  The new renderbuffer's refcount will
420*61046927SAndroid Build Coastguard Worker  * be incremented.  The old renderbuffer's refcount will be decremented.
421*61046927SAndroid Build Coastguard Worker  * This is normally only called from the _mesa_reference_renderbuffer() macro
422*61046927SAndroid Build Coastguard Worker  * when there's a real pointer change.
423*61046927SAndroid Build Coastguard Worker  */
424*61046927SAndroid Build Coastguard Worker void
_mesa_reference_renderbuffer_(struct gl_renderbuffer ** ptr,struct gl_renderbuffer * rb)425*61046927SAndroid Build Coastguard Worker _mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr,
426*61046927SAndroid Build Coastguard Worker                               struct gl_renderbuffer *rb)
427*61046927SAndroid Build Coastguard Worker {
428*61046927SAndroid Build Coastguard Worker    if (*ptr) {
429*61046927SAndroid Build Coastguard Worker       /* Unreference the old renderbuffer */
430*61046927SAndroid Build Coastguard Worker       struct gl_renderbuffer *oldRb = *ptr;
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker       assert(oldRb->RefCount > 0);
433*61046927SAndroid Build Coastguard Worker 
434*61046927SAndroid Build Coastguard Worker       if (p_atomic_dec_zero(&oldRb->RefCount)) {
435*61046927SAndroid Build Coastguard Worker          GET_CURRENT_CONTEXT(ctx);
436*61046927SAndroid Build Coastguard Worker          oldRb->Delete(ctx, oldRb);
437*61046927SAndroid Build Coastguard Worker       }
438*61046927SAndroid Build Coastguard Worker    }
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker    if (rb) {
441*61046927SAndroid Build Coastguard Worker       /* reference new renderbuffer */
442*61046927SAndroid Build Coastguard Worker       p_atomic_inc(&rb->RefCount);
443*61046927SAndroid Build Coastguard Worker    }
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker    *ptr = rb;
446*61046927SAndroid Build Coastguard Worker }
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker void
_mesa_map_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** mapOut,GLint * rowStrideOut,bool flip_y)449*61046927SAndroid Build Coastguard Worker _mesa_map_renderbuffer(struct gl_context *ctx,
450*61046927SAndroid Build Coastguard Worker                        struct gl_renderbuffer *rb,
451*61046927SAndroid Build Coastguard Worker                        GLuint x, GLuint y, GLuint w, GLuint h,
452*61046927SAndroid Build Coastguard Worker                        GLbitfield mode,
453*61046927SAndroid Build Coastguard Worker                        GLubyte **mapOut, GLint *rowStrideOut,
454*61046927SAndroid Build Coastguard Worker                        bool flip_y)
455*61046927SAndroid Build Coastguard Worker {
456*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = ctx->pipe;
457*61046927SAndroid Build Coastguard Worker    const GLboolean invert = flip_y;
458*61046927SAndroid Build Coastguard Worker    GLuint y2;
459*61046927SAndroid Build Coastguard Worker    GLubyte *map;
460*61046927SAndroid Build Coastguard Worker 
461*61046927SAndroid Build Coastguard Worker    if (rb->software) {
462*61046927SAndroid Build Coastguard Worker       /* software-allocated renderbuffer (probably an accum buffer) */
463*61046927SAndroid Build Coastguard Worker       if (rb->data) {
464*61046927SAndroid Build Coastguard Worker          GLint bpp = _mesa_get_format_bytes(rb->Format);
465*61046927SAndroid Build Coastguard Worker          GLint stride = _mesa_format_row_stride(rb->Format,
466*61046927SAndroid Build Coastguard Worker                                                 rb->Width);
467*61046927SAndroid Build Coastguard Worker          *mapOut = (GLubyte *) rb->data + y * stride + x * bpp;
468*61046927SAndroid Build Coastguard Worker          *rowStrideOut = stride;
469*61046927SAndroid Build Coastguard Worker       }
470*61046927SAndroid Build Coastguard Worker       else {
471*61046927SAndroid Build Coastguard Worker          *mapOut = NULL;
472*61046927SAndroid Build Coastguard Worker          *rowStrideOut = 0;
473*61046927SAndroid Build Coastguard Worker       }
474*61046927SAndroid Build Coastguard Worker       return;
475*61046927SAndroid Build Coastguard Worker    }
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker    /* Check for unexpected flags */
478*61046927SAndroid Build Coastguard Worker    assert((mode & ~(GL_MAP_READ_BIT |
479*61046927SAndroid Build Coastguard Worker                     GL_MAP_WRITE_BIT |
480*61046927SAndroid Build Coastguard Worker                     GL_MAP_INVALIDATE_RANGE_BIT)) == 0);
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    const enum pipe_map_flags transfer_flags =
483*61046927SAndroid Build Coastguard Worker       _mesa_access_flags_to_transfer_flags(mode, false);
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker    /* Note: y=0=bottom of buffer while y2=0=top of buffer.
486*61046927SAndroid Build Coastguard Worker     * 'invert' will be true for window-system buffers and false for
487*61046927SAndroid Build Coastguard Worker     * user-allocated renderbuffers and textures.
488*61046927SAndroid Build Coastguard Worker     */
489*61046927SAndroid Build Coastguard Worker    if (invert)
490*61046927SAndroid Build Coastguard Worker       y2 = rb->Height - y - h;
491*61046927SAndroid Build Coastguard Worker    else
492*61046927SAndroid Build Coastguard Worker       y2 = y;
493*61046927SAndroid Build Coastguard Worker 
494*61046927SAndroid Build Coastguard Worker     map = pipe_texture_map(pipe,
495*61046927SAndroid Build Coastguard Worker                             rb->texture,
496*61046927SAndroid Build Coastguard Worker                             rb->surface->u.tex.level,
497*61046927SAndroid Build Coastguard Worker                             rb->surface->u.tex.first_layer,
498*61046927SAndroid Build Coastguard Worker                             transfer_flags, x, y2, w, h, &rb->transfer);
499*61046927SAndroid Build Coastguard Worker    if (map) {
500*61046927SAndroid Build Coastguard Worker       if (invert) {
501*61046927SAndroid Build Coastguard Worker          *rowStrideOut = -(int) rb->transfer->stride;
502*61046927SAndroid Build Coastguard Worker          map += (h - 1) * rb->transfer->stride;
503*61046927SAndroid Build Coastguard Worker       }
504*61046927SAndroid Build Coastguard Worker       else {
505*61046927SAndroid Build Coastguard Worker          *rowStrideOut = rb->transfer->stride;
506*61046927SAndroid Build Coastguard Worker       }
507*61046927SAndroid Build Coastguard Worker       *mapOut = map;
508*61046927SAndroid Build Coastguard Worker    }
509*61046927SAndroid Build Coastguard Worker    else {
510*61046927SAndroid Build Coastguard Worker       *mapOut = NULL;
511*61046927SAndroid Build Coastguard Worker       *rowStrideOut = 0;
512*61046927SAndroid Build Coastguard Worker    }
513*61046927SAndroid Build Coastguard Worker }
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker void
_mesa_unmap_renderbuffer(struct gl_context * ctx,struct gl_renderbuffer * rb)516*61046927SAndroid Build Coastguard Worker _mesa_unmap_renderbuffer(struct gl_context *ctx,
517*61046927SAndroid Build Coastguard Worker                          struct gl_renderbuffer *rb)
518*61046927SAndroid Build Coastguard Worker {
519*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = ctx->pipe;
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker    if (rb->software) {
522*61046927SAndroid Build Coastguard Worker       /* software-allocated renderbuffer (probably an accum buffer) */
523*61046927SAndroid Build Coastguard Worker       return;
524*61046927SAndroid Build Coastguard Worker    }
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker    pipe_texture_unmap(pipe, rb->transfer);
527*61046927SAndroid Build Coastguard Worker    rb->transfer = NULL;
528*61046927SAndroid Build Coastguard Worker }
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker void
_mesa_regen_renderbuffer_surface(struct gl_context * ctx,struct gl_renderbuffer * rb)531*61046927SAndroid Build Coastguard Worker _mesa_regen_renderbuffer_surface(struct gl_context *ctx,
532*61046927SAndroid Build Coastguard Worker                                  struct gl_renderbuffer *rb)
533*61046927SAndroid Build Coastguard Worker {
534*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = ctx->pipe;
535*61046927SAndroid Build Coastguard Worker    struct pipe_resource *resource = rb->texture;
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker    struct pipe_surface **psurf =
538*61046927SAndroid Build Coastguard Worker       rb->surface_srgb ? &rb->surface_srgb : &rb->surface_linear;
539*61046927SAndroid Build Coastguard Worker    struct pipe_surface *surf = *psurf;
540*61046927SAndroid Build Coastguard Worker    /* create a new pipe_surface */
541*61046927SAndroid Build Coastguard Worker    struct pipe_surface surf_tmpl;
542*61046927SAndroid Build Coastguard Worker    memset(&surf_tmpl, 0, sizeof(surf_tmpl));
543*61046927SAndroid Build Coastguard Worker    surf_tmpl.format = surf->format;
544*61046927SAndroid Build Coastguard Worker    surf_tmpl.nr_samples = rb->rtt_nr_samples;
545*61046927SAndroid Build Coastguard Worker    surf_tmpl.u.tex.level = surf->u.tex.level;
546*61046927SAndroid Build Coastguard Worker    surf_tmpl.u.tex.first_layer = surf->u.tex.first_layer;
547*61046927SAndroid Build Coastguard Worker    surf_tmpl.u.tex.last_layer = surf->u.tex.last_layer;
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker    /* create -> destroy to avoid blowing up cached surfaces */
550*61046927SAndroid Build Coastguard Worker    surf = pipe->create_surface(pipe, resource, &surf_tmpl);
551*61046927SAndroid Build Coastguard Worker    pipe_surface_release(pipe, psurf);
552*61046927SAndroid Build Coastguard Worker    *psurf = surf;
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker    rb->surface = *psurf;
555*61046927SAndroid Build Coastguard Worker }
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker /**
558*61046927SAndroid Build Coastguard Worker  * Create or update the pipe_surface of a FBO renderbuffer.
559*61046927SAndroid Build Coastguard Worker  * This is usually called after st_finalize_texture.
560*61046927SAndroid Build Coastguard Worker  */
561*61046927SAndroid Build Coastguard Worker void
_mesa_update_renderbuffer_surface(struct gl_context * ctx,struct gl_renderbuffer * rb)562*61046927SAndroid Build Coastguard Worker _mesa_update_renderbuffer_surface(struct gl_context *ctx,
563*61046927SAndroid Build Coastguard Worker                                   struct gl_renderbuffer *rb)
564*61046927SAndroid Build Coastguard Worker {
565*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = ctx->pipe;
566*61046927SAndroid Build Coastguard Worker    struct pipe_resource *resource = rb->texture;
567*61046927SAndroid Build Coastguard Worker    const struct gl_texture_object *stTexObj = NULL;
568*61046927SAndroid Build Coastguard Worker    unsigned rtt_width = rb->Width;
569*61046927SAndroid Build Coastguard Worker    unsigned rtt_height = rb->Height;
570*61046927SAndroid Build Coastguard Worker    unsigned rtt_depth = rb->Depth;
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker    /*
573*61046927SAndroid Build Coastguard Worker     * For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
574*61046927SAndroid Build Coastguard Worker     * the format of rb->texture is linear (because we have no control over
575*61046927SAndroid Build Coastguard Worker     * the format).  Check rb->Format instead of rb->texture->format
576*61046927SAndroid Build Coastguard Worker     * to determine if the rb is sRGB-capable.
577*61046927SAndroid Build Coastguard Worker     */
578*61046927SAndroid Build Coastguard Worker    bool enable_srgb = ctx->Color.sRGBEnabled &&
579*61046927SAndroid Build Coastguard Worker       _mesa_is_format_srgb(rb->Format);
580*61046927SAndroid Build Coastguard Worker    enum pipe_format format = resource->format;
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker    if (rb->is_rtt) {
583*61046927SAndroid Build Coastguard Worker       stTexObj = rb->TexImage->TexObject;
584*61046927SAndroid Build Coastguard Worker       if (stTexObj->surface_based)
585*61046927SAndroid Build Coastguard Worker          format = stTexObj->surface_format;
586*61046927SAndroid Build Coastguard Worker    }
587*61046927SAndroid Build Coastguard Worker 
588*61046927SAndroid Build Coastguard Worker    format = enable_srgb ? util_format_srgb(format) : util_format_linear(format);
589*61046927SAndroid Build Coastguard Worker 
590*61046927SAndroid Build Coastguard Worker    if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
591*61046927SAndroid Build Coastguard Worker       rtt_depth = rtt_height;
592*61046927SAndroid Build Coastguard Worker       rtt_height = 1;
593*61046927SAndroid Build Coastguard Worker    }
594*61046927SAndroid Build Coastguard Worker 
595*61046927SAndroid Build Coastguard Worker    /* find matching mipmap level size */
596*61046927SAndroid Build Coastguard Worker    unsigned level;
597*61046927SAndroid Build Coastguard Worker    for (level = 0; level <= resource->last_level; level++) {
598*61046927SAndroid Build Coastguard Worker       if (u_minify(resource->width0, level) == rtt_width &&
599*61046927SAndroid Build Coastguard Worker           u_minify(resource->height0, level) == rtt_height &&
600*61046927SAndroid Build Coastguard Worker           (resource->target != PIPE_TEXTURE_3D ||
601*61046927SAndroid Build Coastguard Worker            u_minify(resource->depth0, level) == rtt_depth)) {
602*61046927SAndroid Build Coastguard Worker          break;
603*61046927SAndroid Build Coastguard Worker       }
604*61046927SAndroid Build Coastguard Worker    }
605*61046927SAndroid Build Coastguard Worker    assert(level <= resource->last_level);
606*61046927SAndroid Build Coastguard Worker 
607*61046927SAndroid Build Coastguard Worker    /* determine the layer bounds */
608*61046927SAndroid Build Coastguard Worker    unsigned first_layer, last_layer;
609*61046927SAndroid Build Coastguard Worker    if (rb->rtt_numviews) {
610*61046927SAndroid Build Coastguard Worker       first_layer = rb->rtt_slice;
611*61046927SAndroid Build Coastguard Worker       last_layer = first_layer + rb->rtt_numviews - 1;
612*61046927SAndroid Build Coastguard Worker    } else if (rb->rtt_layered) {
613*61046927SAndroid Build Coastguard Worker       first_layer = 0;
614*61046927SAndroid Build Coastguard Worker       last_layer = util_max_layer(rb->texture, level);
615*61046927SAndroid Build Coastguard Worker    }
616*61046927SAndroid Build Coastguard Worker    else {
617*61046927SAndroid Build Coastguard Worker       first_layer =
618*61046927SAndroid Build Coastguard Worker       last_layer = rb->rtt_face + rb->rtt_slice;
619*61046927SAndroid Build Coastguard Worker    }
620*61046927SAndroid Build Coastguard Worker 
621*61046927SAndroid Build Coastguard Worker    /* Adjust for texture views */
622*61046927SAndroid Build Coastguard Worker    if (rb->is_rtt && resource->array_size > 1 &&
623*61046927SAndroid Build Coastguard Worker        stTexObj->Immutable) {
624*61046927SAndroid Build Coastguard Worker       const struct gl_texture_object *tex = stTexObj;
625*61046927SAndroid Build Coastguard Worker       first_layer += tex->Attrib.MinLayer;
626*61046927SAndroid Build Coastguard Worker       if (!rb->rtt_layered)
627*61046927SAndroid Build Coastguard Worker          last_layer += tex->Attrib.MinLayer;
628*61046927SAndroid Build Coastguard Worker       else
629*61046927SAndroid Build Coastguard Worker          last_layer = MIN2(first_layer + tex->Attrib.NumLayers - 1,
630*61046927SAndroid Build Coastguard Worker                            last_layer);
631*61046927SAndroid Build Coastguard Worker    }
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker    struct pipe_surface **psurf =
634*61046927SAndroid Build Coastguard Worker       enable_srgb ? &rb->surface_srgb : &rb->surface_linear;
635*61046927SAndroid Build Coastguard Worker    struct pipe_surface *surf = *psurf;
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker    if (!surf ||
638*61046927SAndroid Build Coastguard Worker        surf->texture->nr_samples != rb->NumSamples ||
639*61046927SAndroid Build Coastguard Worker        surf->texture->nr_storage_samples != rb->NumStorageSamples ||
640*61046927SAndroid Build Coastguard Worker        surf->format != format ||
641*61046927SAndroid Build Coastguard Worker        surf->texture != resource ||
642*61046927SAndroid Build Coastguard Worker        surf->width != rtt_width ||
643*61046927SAndroid Build Coastguard Worker        surf->height != rtt_height ||
644*61046927SAndroid Build Coastguard Worker        surf->nr_samples != rb->rtt_nr_samples ||
645*61046927SAndroid Build Coastguard Worker        surf->u.tex.level != level ||
646*61046927SAndroid Build Coastguard Worker        surf->u.tex.first_layer != first_layer ||
647*61046927SAndroid Build Coastguard Worker        surf->u.tex.last_layer != last_layer) {
648*61046927SAndroid Build Coastguard Worker       /* create a new pipe_surface */
649*61046927SAndroid Build Coastguard Worker       struct pipe_surface surf_tmpl;
650*61046927SAndroid Build Coastguard Worker       memset(&surf_tmpl, 0, sizeof(surf_tmpl));
651*61046927SAndroid Build Coastguard Worker       surf_tmpl.format = format;
652*61046927SAndroid Build Coastguard Worker       surf_tmpl.nr_samples = rb->rtt_nr_samples;
653*61046927SAndroid Build Coastguard Worker       surf_tmpl.u.tex.level = level;
654*61046927SAndroid Build Coastguard Worker       surf_tmpl.u.tex.first_layer = first_layer;
655*61046927SAndroid Build Coastguard Worker       surf_tmpl.u.tex.last_layer = last_layer;
656*61046927SAndroid Build Coastguard Worker 
657*61046927SAndroid Build Coastguard Worker       /* create -> destroy to avoid blowing up cached surfaces */
658*61046927SAndroid Build Coastguard Worker       struct pipe_surface *surf = pipe->create_surface(pipe, resource, &surf_tmpl);
659*61046927SAndroid Build Coastguard Worker       pipe_surface_release(pipe, psurf);
660*61046927SAndroid Build Coastguard Worker       *psurf = surf;
661*61046927SAndroid Build Coastguard Worker    }
662*61046927SAndroid Build Coastguard Worker    rb->surface = *psurf;
663*61046927SAndroid Build Coastguard Worker }
664