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