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