~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/mesa/main/renderbuffer.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 "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
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
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
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
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
300
 
_mesa_init_renderbuffer(struct gl_renderbuffer *rb, GLuint name)
301
 
{
302
 
   GET_CURRENT_CONTEXT(ctx);
303
 
 
304
 
   rb->ClassID = 0;
305
 
   rb->Name = name;
306
 
   rb->RefCount = 1;
307
 
   rb->Delete = delete_renderbuffer;
308
 
 
309
 
   /* The rest of these should be set later by the caller of this function or
310
 
    * the AllocStorage method:
311
 
    */
312
 
   rb->AllocStorage = NULL;
313
 
 
314
 
   rb->Width = 0;
315
 
   rb->Height = 0;
316
 
   rb->Depth = 0;
317
 
 
318
 
   /* In GL 3, the initial format is GL_RGBA according to Table 6.26
319
 
    * on page 302 of the GL 3.3 spec.
320
 
    *
321
 
    * In GLES 3, the initial format is GL_RGBA4 according to Table 6.15
322
 
    * on page 258 of the GLES 3.0.4 spec.
323
 
    *
324
 
    * If the context is current, set the initial format based on the
325
 
    * specs. If the context is not current, we cannot determine the
326
 
    * API, so default to GL_RGBA.
327
 
    */
328
 
   if (ctx && _mesa_is_gles(ctx)) {
329
 
      rb->InternalFormat = GL_RGBA4;
330
 
   } else {
331
 
      rb->InternalFormat = GL_RGBA;
332
 
   }
333
 
 
334
 
   rb->Format = MESA_FORMAT_NONE;
335
 
 
336
 
   rb->AllocStorage = renderbuffer_alloc_storage;
337
 
}
338
 
 
339
 
static void
340
 
validate_and_init_renderbuffer_attachment(struct gl_framebuffer *fb,
341
 
                                          gl_buffer_index bufferName,
342
 
                                          struct gl_renderbuffer *rb)
343
 
{
344
 
   assert(fb);
345
 
   assert(rb);
346
 
   assert(bufferName < BUFFER_COUNT);
347
 
 
348
 
   /* There should be no previous renderbuffer on this attachment point,
349
 
    * with the exception of depth/stencil since the same renderbuffer may
350
 
    * be used for both.
351
 
    */
352
 
   assert(bufferName == BUFFER_DEPTH ||
353
 
          bufferName == BUFFER_STENCIL ||
354
 
          fb->Attachment[bufferName].Renderbuffer == NULL);
355
 
 
356
 
   /* winsys vs. user-created buffer cross check */
357
 
   if (_mesa_is_user_fbo(fb)) {
358
 
      assert(rb->Name);
359
 
   }
360
 
   else {
361
 
      assert(!rb->Name);
362
 
   }
363
 
 
364
 
   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
365
 
   fb->Attachment[bufferName].Complete = GL_TRUE;
366
 
}
367
 
 
368
 
 
369
 
/**
370
 
 * Attach a renderbuffer to a framebuffer.
371
 
 * \param bufferName  one of the BUFFER_x tokens
372
 
 *
373
 
 * This function avoids adding a reference and is therefore intended to be
374
 
 * used with a freshly created renderbuffer.
375
 
 */
376
 
void
377
 
_mesa_attach_and_own_rb(struct gl_framebuffer *fb,
378
 
                        gl_buffer_index bufferName,
379
 
                        struct gl_renderbuffer *rb)
380
 
{
381
 
   assert(rb->RefCount == 1);
382
 
 
383
 
   validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
384
 
 
385
 
   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
386
 
                                NULL);
387
 
   fb->Attachment[bufferName].Renderbuffer = rb;
388
 
}
389
 
 
390
 
/**
391
 
 * Attach a renderbuffer to a framebuffer.
392
 
 * \param bufferName  one of the BUFFER_x tokens
393
 
 */
394
 
void
395
 
_mesa_attach_and_reference_rb(struct gl_framebuffer *fb,
396
 
                              gl_buffer_index bufferName,
397
 
                              struct gl_renderbuffer *rb)
398
 
{
399
 
   validate_and_init_renderbuffer_attachment(fb, bufferName, rb);
400
 
   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
401
 
}
402
 
 
403
 
 
404
 
/**
405
 
 * Remove the named renderbuffer from the given framebuffer.
406
 
 * \param bufferName  one of the BUFFER_x tokens
407
 
 */
408
 
void
409
 
_mesa_remove_renderbuffer(struct gl_framebuffer *fb,
410
 
                          gl_buffer_index bufferName)
411
 
{
412
 
   assert(bufferName < BUFFER_COUNT);
413
 
   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
414
 
                                NULL);
415
 
}
416
 
 
417
 
 
418
 
/**
419
 
 * Set *ptr to point to rb.  If *ptr points to another renderbuffer,
420
 
 * dereference that buffer first.  The new renderbuffer's refcount will
421
 
 * be incremented.  The old renderbuffer's refcount will be decremented.
422
 
 * This is normally only called from the _mesa_reference_renderbuffer() macro
423
 
 * when there's a real pointer change.
424
 
 */
425
 
void
426
 
_mesa_reference_renderbuffer_(struct gl_renderbuffer **ptr,
427
 
                              struct gl_renderbuffer *rb)
428
 
{
429
 
   if (*ptr) {
430
 
      /* Unreference the old renderbuffer */
431
 
      struct gl_renderbuffer *oldRb = *ptr;
432
 
 
433
 
      assert(oldRb->RefCount > 0);
434
 
 
435
 
      if (p_atomic_dec_zero(&oldRb->RefCount)) {
436
 
         GET_CURRENT_CONTEXT(ctx);
437
 
         oldRb->Delete(ctx, oldRb);
438
 
      }
439
 
   }
440
 
 
441
 
   if (rb) {
442
 
      /* reference new renderbuffer */
443
 
      p_atomic_inc(&rb->RefCount);
444
 
   }
445
 
 
446
 
   *ptr = rb;
447
 
}
448
 
 
449
 
void
450
 
_mesa_map_renderbuffer(struct gl_context *ctx,
451
 
                       struct gl_renderbuffer *rb,
452
 
                       GLuint x, GLuint y, GLuint w, GLuint h,
453
 
                       GLbitfield mode,
454
 
                       GLubyte **mapOut, GLint *rowStrideOut,
455
 
                       bool flip_y)
456
 
{
457
 
   struct pipe_context *pipe = ctx->pipe;
458
 
   const GLboolean invert = flip_y;
459
 
   GLuint y2;
460
 
   GLubyte *map;
461
 
 
462
 
   if (rb->software) {
463
 
      /* software-allocated renderbuffer (probably an accum buffer) */
464
 
      if (rb->data) {
465
 
         GLint bpp = _mesa_get_format_bytes(rb->Format);
466
 
         GLint stride = _mesa_format_row_stride(rb->Format,
467
 
                                                rb->Width);
468
 
         *mapOut = (GLubyte *) rb->data + y * stride + x * bpp;
469
 
         *rowStrideOut = stride;
470
 
      }
471
 
      else {
472
 
         *mapOut = NULL;
473
 
         *rowStrideOut = 0;
474
 
      }
475
 
      return;
476
 
   }
477
 
 
478
 
   /* Check for unexpected flags */
479
 
   assert((mode & ~(GL_MAP_READ_BIT |
480
 
                    GL_MAP_WRITE_BIT |
481
 
                    GL_MAP_INVALIDATE_RANGE_BIT)) == 0);
482
 
 
483
 
   const enum pipe_map_flags transfer_flags =
484
 
      _mesa_access_flags_to_transfer_flags(mode, false);
485
 
 
486
 
   /* Note: y=0=bottom of buffer while y2=0=top of buffer.
487
 
    * 'invert' will be true for window-system buffers and false for
488
 
    * user-allocated renderbuffers and textures.
489
 
    */
490
 
   if (invert)
491
 
      y2 = rb->Height - y - h;
492
 
   else
493
 
      y2 = y;
494
 
 
495
 
    map = pipe_texture_map(pipe,
496
 
                            rb->texture,
497
 
                            rb->surface->u.tex.level,
498
 
                            rb->surface->u.tex.first_layer,
499
 
                            transfer_flags, x, y2, w, h, &rb->transfer);
500
 
   if (map) {
501
 
      if (invert) {
502
 
         *rowStrideOut = -(int) rb->transfer->stride;
503
 
         map += (h - 1) * rb->transfer->stride;
504
 
      }
505
 
      else {
506
 
         *rowStrideOut = rb->transfer->stride;
507
 
      }
508
 
      *mapOut = map;
509
 
   }
510
 
   else {
511
 
      *mapOut = NULL;
512
 
      *rowStrideOut = 0;
513
 
   }
514
 
}
515
 
 
516
 
void
517
 
_mesa_unmap_renderbuffer(struct gl_context *ctx,
518
 
                         struct gl_renderbuffer *rb)
519
 
{
520
 
   struct pipe_context *pipe = ctx->pipe;
521
 
 
522
 
   if (rb->software) {
523
 
      /* software-allocated renderbuffer (probably an accum buffer) */
524
 
      return;
525
 
   }
526
 
 
527
 
   pipe_texture_unmap(pipe, rb->transfer);
528
 
   rb->transfer = NULL;
529
 
}
530
 
 
531
 
void
532
 
_mesa_regen_renderbuffer_surface(struct gl_context *ctx,
533
 
                                 struct gl_renderbuffer *rb)
534
 
{
535
 
   struct pipe_context *pipe = ctx->pipe;
536
 
   struct pipe_resource *resource = rb->texture;
537
 
 
538
 
   struct pipe_surface **psurf =
539
 
      rb->surface_srgb ? &rb->surface_srgb : &rb->surface_linear;
540
 
   struct pipe_surface *surf = *psurf;
541
 
   /* create a new pipe_surface */
542
 
   struct pipe_surface surf_tmpl;
543
 
   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
544
 
   surf_tmpl.format = surf->format;
545
 
   surf_tmpl.nr_samples = rb->rtt_nr_samples;
546
 
   surf_tmpl.u.tex.level = surf->u.tex.level;
547
 
   surf_tmpl.u.tex.first_layer = surf->u.tex.first_layer;
548
 
   surf_tmpl.u.tex.last_layer = surf->u.tex.last_layer;
549
 
 
550
 
   /* create -> destroy to avoid blowing up cached surfaces */
551
 
   surf = pipe->create_surface(pipe, resource, &surf_tmpl);
552
 
   pipe_surface_release(pipe, psurf);
553
 
   *psurf = surf;
554
 
 
555
 
   rb->surface = *psurf;
556
 
}
557
 
 
558
 
/**
559
 
 * Create or update the pipe_surface of a FBO renderbuffer.
560
 
 * This is usually called after st_finalize_texture.
561
 
 */
562
 
void
563
 
_mesa_update_renderbuffer_surface(struct gl_context *ctx,
564
 
                                  struct gl_renderbuffer *rb)
565
 
{
566
 
   struct pipe_context *pipe = ctx->pipe;
567
 
   struct pipe_resource *resource = rb->texture;
568
 
   const struct gl_texture_object *stTexObj = NULL;
569
 
   unsigned rtt_width = rb->Width;
570
 
   unsigned rtt_height = rb->Height;
571
 
   unsigned rtt_depth = rb->Depth;
572
 
 
573
 
   /*
574
 
    * For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
575
 
    * the format of rb->texture is linear (because we have no control over
576
 
    * the format).  Check rb->Format instead of rb->texture->format
577
 
    * to determine if the rb is sRGB-capable.
578
 
    */
579
 
   boolean enable_srgb = ctx->Color.sRGBEnabled &&
580
 
      _mesa_is_format_srgb(rb->Format);
581
 
   enum pipe_format format = resource->format;
582
 
 
583
 
   if (rb->is_rtt) {
584
 
      stTexObj = rb->TexImage->TexObject;
585
 
      if (stTexObj->surface_based)
586
 
         format = stTexObj->surface_format;
587
 
   }
588
 
 
589
 
   format = enable_srgb ? util_format_srgb(format) : util_format_linear(format);
590
 
 
591
 
   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
592
 
      rtt_depth = rtt_height;
593
 
      rtt_height = 1;
594
 
   }
595
 
 
596
 
   /* find matching mipmap level size */
597
 
   unsigned level;
598
 
   for (level = 0; level <= resource->last_level; level++) {
599
 
      if (u_minify(resource->width0, level) == rtt_width &&
600
 
          u_minify(resource->height0, level) == rtt_height &&
601
 
          (resource->target != PIPE_TEXTURE_3D ||
602
 
           u_minify(resource->depth0, level) == rtt_depth)) {
603
 
         break;
604
 
      }
605
 
   }
606
 
   assert(level <= resource->last_level);
607
 
 
608
 
   /* determine the layer bounds */
609
 
   unsigned first_layer, last_layer;
610
 
   if (rb->rtt_layered) {
611
 
      first_layer = 0;
612
 
      last_layer = util_max_layer(rb->texture, level);
613
 
   }
614
 
   else {
615
 
      first_layer =
616
 
      last_layer = rb->rtt_face + rb->rtt_slice;
617
 
   }
618
 
 
619
 
   /* Adjust for texture views */
620
 
   if (rb->is_rtt && resource->array_size > 1 &&
621
 
       stTexObj->Immutable) {
622
 
      const struct gl_texture_object *tex = stTexObj;
623
 
      first_layer += tex->Attrib.MinLayer;
624
 
      if (!rb->rtt_layered)
625
 
         last_layer += tex->Attrib.MinLayer;
626
 
      else
627
 
         last_layer = MIN2(first_layer + tex->Attrib.NumLayers - 1,
628
 
                           last_layer);
629
 
   }
630
 
 
631
 
   struct pipe_surface **psurf =
632
 
      enable_srgb ? &rb->surface_srgb : &rb->surface_linear;
633
 
   struct pipe_surface *surf = *psurf;
634
 
 
635
 
   if (!surf ||
636
 
       surf->texture->nr_samples != rb->NumSamples ||
637
 
       surf->texture->nr_storage_samples != rb->NumStorageSamples ||
638
 
       surf->format != format ||
639
 
       surf->texture != resource ||
640
 
       surf->width != rtt_width ||
641
 
       surf->height != rtt_height ||
642
 
       surf->nr_samples != rb->rtt_nr_samples ||
643
 
       surf->u.tex.level != level ||
644
 
       surf->u.tex.first_layer != first_layer ||
645
 
       surf->u.tex.last_layer != last_layer) {
646
 
      /* create a new pipe_surface */
647
 
      struct pipe_surface surf_tmpl;
648
 
      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
649
 
      surf_tmpl.format = format;
650
 
      surf_tmpl.nr_samples = rb->rtt_nr_samples;
651
 
      surf_tmpl.u.tex.level = level;
652
 
      surf_tmpl.u.tex.first_layer = first_layer;
653
 
      surf_tmpl.u.tex.last_layer = last_layer;
654
 
 
655
 
      /* create -> destroy to avoid blowing up cached surfaces */
656
 
      struct pipe_surface *surf = pipe->create_surface(pipe, resource, &surf_tmpl);
657
 
      pipe_surface_release(pipe, psurf);
658
 
      *psurf = surf;
659
 
   }
660
 
   rb->surface = *psurf;
661
 
}