1/**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
4 * 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
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29/**
30 * Framebuffer/renderbuffer functions.
31 *
32 * \author Brian Paul
33 */
34
35
36#include "main/imports.h"
37#include "main/context.h"
38#include "main/fbobject.h"
39#include "main/framebuffer.h"
40#include "main/glformats.h"
41#include "main/macros.h"
42#include "main/renderbuffer.h"
43#include "main/state.h"
44
45#include "pipe/p_context.h"
46#include "pipe/p_defines.h"
47#include "pipe/p_screen.h"
48#include "st_atom.h"
49#include "st_context.h"
50#include "st_cb_bufferobjects.h"
51#include "st_cb_fbo.h"
52#include "st_cb_flush.h"
53#include "st_cb_texture.h"
54#include "st_format.h"
55#include "st_texture.h"
56#include "st_util.h"
57#include "st_manager.h"
58
59#include "util/u_format.h"
60#include "util/u_inlines.h"
61#include "util/u_surface.h"
62
63
64static GLboolean
65st_renderbuffer_alloc_sw_storage(struct gl_context * ctx,
66                                 struct gl_renderbuffer *rb,
67                                 GLenum internalFormat,
68                                 GLuint width, GLuint height)
69{
70   struct st_context *st = st_context(ctx);
71   struct st_renderbuffer *strb = st_renderbuffer(rb);
72   enum pipe_format format;
73   size_t size;
74
75   free(strb->data);
76   strb->data = NULL;
77
78   if (internalFormat == GL_RGBA16_SNORM) {
79      /* Special case for software accum buffers.  Otherwise, if the
80       * call to st_choose_renderbuffer_format() fails (because the
81       * driver doesn't support signed 16-bit/channel colors) we'd
82       * just return without allocating the software accum buffer.
83       */
84      format = PIPE_FORMAT_R16G16B16A16_SNORM;
85   }
86   else {
87      format = st_choose_renderbuffer_format(st, internalFormat, 0, 0);
88
89      /* Not setting gl_renderbuffer::Format here will cause
90       * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
91       */
92      if (format == PIPE_FORMAT_NONE) {
93         return GL_TRUE;
94      }
95   }
96
97   strb->Base.Format = st_pipe_format_to_mesa_format(format);
98
99   size = _mesa_format_image_size(strb->Base.Format, width, height, 1);
100   strb->data = malloc(size);
101   return strb->data != NULL;
102}
103
104
105/**
106 * gl_renderbuffer::AllocStorage()
107 * This is called to allocate the original drawing surface, and
108 * during window resize.
109 */
110static GLboolean
111st_renderbuffer_alloc_storage(struct gl_context * ctx,
112                              struct gl_renderbuffer *rb,
113                              GLenum internalFormat,
114                              GLuint width, GLuint height)
115{
116   struct st_context *st = st_context(ctx);
117   struct pipe_screen *screen = st->pipe->screen;
118   struct st_renderbuffer *strb = st_renderbuffer(rb);
119   enum pipe_format format = PIPE_FORMAT_NONE;
120   struct pipe_resource templ;
121
122   /* init renderbuffer fields */
123   strb->Base.Width  = width;
124   strb->Base.Height = height;
125   strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
126   strb->defined = GL_FALSE;  /* undefined contents now */
127
128   if (strb->software) {
129      return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat,
130                                              width, height);
131   }
132
133   /* Free the old surface and texture
134    */
135   pipe_surface_reference(&strb->surface_srgb, NULL);
136   pipe_surface_reference(&strb->surface_linear, NULL);
137   strb->surface = NULL;
138   pipe_resource_reference(&strb->texture, NULL);
139
140   /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear
141    * formats.
142    */
143   if (!ctx->Extensions.EXT_sRGB) {
144      internalFormat = _mesa_get_linear_internalformat(internalFormat);
145   }
146
147   /* Handle multisample renderbuffers first.
148    *
149    * From ARB_framebuffer_object:
150    *   If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero.
151    *   Otherwise <samples> represents a request for a desired minimum
152    *   number of samples. Since different implementations may support
153    *   different sample counts for multisampled rendering, the actual
154    *   number of samples allocated for the renderbuffer image is
155    *   implementation dependent.  However, the resulting value for
156    *   RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal
157    *   to <samples> and no more than the next larger sample count supported
158    *   by the implementation.
159    *
160    * Find the supported number of samples >= rb->NumSamples
161    */
162   if (rb->NumSamples > 0) {
163      unsigned start, start_storage;
164
165      if (ctx->Const.MaxSamples > 1 &&  rb->NumSamples == 1) {
166         /* don't try num_samples = 1 with drivers that support real msaa */
167         start = 2;
168         start_storage = 2;
169      } else {
170         start = rb->NumSamples;
171         start_storage = rb->NumStorageSamples;
172      }
173
174      if (ctx->Extensions.AMD_framebuffer_multisample_advanced) {
175         if (rb->_BaseFormat == GL_DEPTH_COMPONENT ||
176             rb->_BaseFormat == GL_DEPTH_STENCIL ||
177             rb->_BaseFormat == GL_STENCIL_INDEX) {
178            /* Find a supported depth-stencil format. */
179            for (unsigned samples = start;
180                 samples <= ctx->Const.MaxDepthStencilFramebufferSamples;
181                 samples++) {
182               format = st_choose_renderbuffer_format(st, internalFormat,
183                                                      samples, samples);
184
185               if (format != PIPE_FORMAT_NONE) {
186                  rb->NumSamples = samples;
187                  rb->NumStorageSamples = samples;
188                  break;
189               }
190            }
191         } else {
192            /* Find a supported color format, samples >= storage_samples. */
193            for (unsigned storage_samples = start_storage;
194                 storage_samples <= ctx->Const.MaxColorFramebufferStorageSamples;
195                 storage_samples++) {
196               for (unsigned samples = MAX2(start, storage_samples);
197                    samples <= ctx->Const.MaxColorFramebufferSamples;
198                    samples++) {
199                  format = st_choose_renderbuffer_format(st, internalFormat,
200                                                         samples,
201                                                         storage_samples);
202
203                  if (format != PIPE_FORMAT_NONE) {
204                     rb->NumSamples = samples;
205                     rb->NumStorageSamples = storage_samples;
206                     goto found;
207                  }
208               }
209            }
210            found:;
211         }
212      } else {
213         for (unsigned samples = start; samples <= ctx->Const.MaxSamples;
214              samples++) {
215            format = st_choose_renderbuffer_format(st, internalFormat,
216                                                   samples, samples);
217
218            if (format != PIPE_FORMAT_NONE) {
219               rb->NumSamples = samples;
220               rb->NumStorageSamples = samples;
221               break;
222            }
223         }
224      }
225   } else {
226      format = st_choose_renderbuffer_format(st, internalFormat, 0, 0);
227   }
228
229   /* Not setting gl_renderbuffer::Format here will cause
230    * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called.
231    */
232   if (format == PIPE_FORMAT_NONE) {
233      return GL_TRUE;
234   }
235
236   strb->Base.Format = st_pipe_format_to_mesa_format(format);
237
238   if (width == 0 || height == 0) {
239      /* if size is zero, nothing to allocate */
240      return GL_TRUE;
241   }
242
243   /* Setup new texture template.
244    */
245   memset(&templ, 0, sizeof(templ));
246   templ.target = st->internal_target;
247   templ.format = format;
248   templ.width0 = width;
249   templ.height0 = height;
250   templ.depth0 = 1;
251   templ.array_size = 1;
252   templ.nr_samples = rb->NumSamples;
253   templ.nr_storage_samples = rb->NumStorageSamples;
254
255   if (util_format_is_depth_or_stencil(format)) {
256      templ.bind = PIPE_BIND_DEPTH_STENCIL;
257   }
258   else if (strb->Base.Name != 0) {
259      /* this is a user-created renderbuffer */
260      templ.bind = PIPE_BIND_RENDER_TARGET;
261   }
262   else {
263      /* this is a window-system buffer */
264      templ.bind = (PIPE_BIND_DISPLAY_TARGET |
265                    PIPE_BIND_RENDER_TARGET);
266   }
267
268   strb->texture = screen->resource_create(screen, &templ);
269
270   if (!strb->texture)
271      return FALSE;
272
273   st_update_renderbuffer_surface(st, strb);
274   return strb->surface != NULL;
275}
276
277
278/**
279 * gl_renderbuffer::Delete()
280 */
281static void
282st_renderbuffer_delete(struct gl_context *ctx, struct gl_renderbuffer *rb)
283{
284   struct st_renderbuffer *strb = st_renderbuffer(rb);
285   if (ctx) {
286      struct st_context *st = st_context(ctx);
287      pipe_surface_release(st->pipe, &strb->surface_srgb);
288      pipe_surface_release(st->pipe, &strb->surface_linear);
289   } else {
290      pipe_surface_release_no_context(&strb->surface_srgb);
291      pipe_surface_release_no_context(&strb->surface_linear);
292   }
293   strb->surface = NULL;
294   pipe_resource_reference(&strb->texture, NULL);
295   free(strb->data);
296   _mesa_delete_renderbuffer(ctx, rb);
297}
298
299
300/**
301 * Called via ctx->Driver.NewRenderbuffer()
302 */
303static struct gl_renderbuffer *
304st_new_renderbuffer(struct gl_context *ctx, GLuint name)
305{
306   struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
307   if (strb) {
308      assert(name != 0);
309      _mesa_init_renderbuffer(&strb->Base, name);
310      strb->Base.Delete = st_renderbuffer_delete;
311      strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
312      return &strb->Base;
313   }
314   return NULL;
315}
316
317
318/**
319 * Allocate a renderbuffer for an on-screen window (not a user-created
320 * renderbuffer).  The window system code determines the format.
321 */
322struct gl_renderbuffer *
323st_new_renderbuffer_fb(enum pipe_format format, unsigned samples, boolean sw)
324{
325   struct st_renderbuffer *strb;
326
327   strb = ST_CALLOC_STRUCT(st_renderbuffer);
328   if (!strb) {
329      _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
330      return NULL;
331   }
332
333   _mesa_init_renderbuffer(&strb->Base, 0);
334   strb->Base.ClassID = 0x4242; /* just a unique value */
335   strb->Base.NumSamples = samples;
336   strb->Base.NumStorageSamples = samples;
337   strb->Base.Format = st_pipe_format_to_mesa_format(format);
338   strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
339   strb->software = sw;
340
341   switch (format) {
342   case PIPE_FORMAT_B10G10R10A2_UNORM:
343   case PIPE_FORMAT_R10G10B10A2_UNORM:
344      strb->Base.InternalFormat = GL_RGB10_A2;
345      break;
346   case PIPE_FORMAT_R10G10B10X2_UNORM:
347   case PIPE_FORMAT_B10G10R10X2_UNORM:
348      strb->Base.InternalFormat = GL_RGB10;
349      break;
350   case PIPE_FORMAT_R8G8B8A8_UNORM:
351   case PIPE_FORMAT_B8G8R8A8_UNORM:
352   case PIPE_FORMAT_A8R8G8B8_UNORM:
353      strb->Base.InternalFormat = GL_RGBA8;
354      break;
355   case PIPE_FORMAT_R8G8B8X8_UNORM:
356   case PIPE_FORMAT_B8G8R8X8_UNORM:
357   case PIPE_FORMAT_X8R8G8B8_UNORM:
358      strb->Base.InternalFormat = GL_RGB8;
359      break;
360   case PIPE_FORMAT_R8G8B8A8_SRGB:
361   case PIPE_FORMAT_B8G8R8A8_SRGB:
362   case PIPE_FORMAT_A8R8G8B8_SRGB:
363      strb->Base.InternalFormat = GL_SRGB8_ALPHA8;
364      break;
365   case PIPE_FORMAT_R8G8B8X8_SRGB:
366   case PIPE_FORMAT_B8G8R8X8_SRGB:
367   case PIPE_FORMAT_X8R8G8B8_SRGB:
368      strb->Base.InternalFormat = GL_SRGB8;
369      break;
370   case PIPE_FORMAT_B5G5R5A1_UNORM:
371      strb->Base.InternalFormat = GL_RGB5_A1;
372      break;
373   case PIPE_FORMAT_B4G4R4A4_UNORM:
374      strb->Base.InternalFormat = GL_RGBA4;
375      break;
376   case PIPE_FORMAT_B5G6R5_UNORM:
377      strb->Base.InternalFormat = GL_RGB565;
378      break;
379   case PIPE_FORMAT_Z16_UNORM:
380      strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
381      break;
382   case PIPE_FORMAT_Z32_UNORM:
383      strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
384      break;
385   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
386   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
387      strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
388      break;
389   case PIPE_FORMAT_Z24X8_UNORM:
390   case PIPE_FORMAT_X8Z24_UNORM:
391      strb->Base.InternalFormat = GL_DEPTH_COMPONENT24;
392      break;
393   case PIPE_FORMAT_S8_UINT:
394      strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
395      break;
396   case PIPE_FORMAT_R16G16B16A16_SNORM:
397      /* accum buffer */
398      strb->Base.InternalFormat = GL_RGBA16_SNORM;
399      break;
400   case PIPE_FORMAT_R16G16B16A16_UNORM:
401      strb->Base.InternalFormat = GL_RGBA16;
402      break;
403   case PIPE_FORMAT_R8_UNORM:
404      strb->Base.InternalFormat = GL_R8;
405      break;
406   case PIPE_FORMAT_R8G8_UNORM:
407      strb->Base.InternalFormat = GL_RG8;
408      break;
409   case PIPE_FORMAT_R16_UNORM:
410      strb->Base.InternalFormat = GL_R16;
411      break;
412   case PIPE_FORMAT_R16G16_UNORM:
413      strb->Base.InternalFormat = GL_RG16;
414      break;
415   case PIPE_FORMAT_R32G32B32A32_FLOAT:
416      strb->Base.InternalFormat = GL_RGBA32F;
417      break;
418   case PIPE_FORMAT_R32G32B32X32_FLOAT:
419      strb->Base.InternalFormat = GL_RGB32F;
420      break;
421   case PIPE_FORMAT_R16G16B16A16_FLOAT:
422      strb->Base.InternalFormat = GL_RGBA16F;
423      break;
424   case PIPE_FORMAT_R16G16B16X16_FLOAT:
425      strb->Base.InternalFormat = GL_RGB16F;
426      break;
427   default:
428      _mesa_problem(NULL,
429                    "Unexpected format %s in st_new_renderbuffer_fb",
430                    util_format_name(format));
431      free(strb);
432      return NULL;
433   }
434
435   /* st-specific methods */
436   strb->Base.Delete = st_renderbuffer_delete;
437   strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
438
439   /* surface is allocated in st_renderbuffer_alloc_storage() */
440   strb->surface = NULL;
441
442   return &strb->Base;
443}
444
445
446/**
447 * Create or update the pipe_surface of a FBO renderbuffer.
448 * This is usually called after st_finalize_texture.
449 */
450void
451st_update_renderbuffer_surface(struct st_context *st,
452                               struct st_renderbuffer *strb)
453{
454   struct pipe_context *pipe = st->pipe;
455   struct pipe_resource *resource = strb->texture;
456   const struct st_texture_object *stTexObj = NULL;
457   unsigned rtt_width = strb->Base.Width;
458   unsigned rtt_height = strb->Base.Height;
459   unsigned rtt_depth = strb->Base.Depth;
460
461   /*
462    * For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
463    * the format of strb->texture is linear (because we have no control over
464    * the format).  Check strb->Base.Format instead of strb->texture->format
465    * to determine if the rb is sRGB-capable.
466    */
467   boolean enable_srgb = st->ctx->Color.sRGBEnabled &&
468      _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB;
469   enum pipe_format format = resource->format;
470
471   if (strb->is_rtt) {
472      stTexObj = st_texture_object(strb->Base.TexImage->TexObject);
473      if (stTexObj->surface_based)
474         format = stTexObj->surface_format;
475   }
476
477   format = enable_srgb ? util_format_srgb(format) : util_format_linear(format);
478
479   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
480      rtt_depth = rtt_height;
481      rtt_height = 1;
482   }
483
484   /* find matching mipmap level size */
485   unsigned level;
486   for (level = 0; level <= resource->last_level; level++) {
487      if (u_minify(resource->width0, level) == rtt_width &&
488          u_minify(resource->height0, level) == rtt_height &&
489          (resource->target != PIPE_TEXTURE_3D ||
490           u_minify(resource->depth0, level) == rtt_depth)) {
491         break;
492      }
493   }
494   assert(level <= resource->last_level);
495
496   /* determine the layer bounds */
497   unsigned first_layer, last_layer;
498   if (strb->rtt_layered) {
499      first_layer = 0;
500      last_layer = util_max_layer(strb->texture, level);
501   }
502   else {
503      first_layer =
504      last_layer = strb->rtt_face + strb->rtt_slice;
505   }
506
507   /* Adjust for texture views */
508   if (strb->is_rtt && resource->array_size > 1 &&
509       stTexObj->base.Immutable) {
510      const struct gl_texture_object *tex = &stTexObj->base;
511      first_layer += tex->MinLayer;
512      if (!strb->rtt_layered)
513         last_layer += tex->MinLayer;
514      else
515         last_layer = MIN2(first_layer + tex->NumLayers - 1, last_layer);
516   }
517
518   struct pipe_surface **psurf =
519      enable_srgb ? &strb->surface_srgb : &strb->surface_linear;
520   struct pipe_surface *surf = *psurf;
521
522   if (!surf ||
523       surf->texture->nr_samples != strb->Base.NumSamples ||
524       surf->texture->nr_storage_samples != strb->Base.NumStorageSamples ||
525       surf->format != format ||
526       surf->texture != resource ||
527       surf->width != rtt_width ||
528       surf->height != rtt_height ||
529       surf->nr_samples != strb->rtt_nr_samples ||
530       surf->u.tex.level != level ||
531       surf->u.tex.first_layer != first_layer ||
532       surf->u.tex.last_layer != last_layer) {
533      /* create a new pipe_surface */
534      struct pipe_surface surf_tmpl;
535      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
536      surf_tmpl.format = format;
537      surf_tmpl.nr_samples = strb->rtt_nr_samples;
538      surf_tmpl.u.tex.level = level;
539      surf_tmpl.u.tex.first_layer = first_layer;
540      surf_tmpl.u.tex.last_layer = last_layer;
541
542      pipe_surface_release(pipe, psurf);
543
544      *psurf = pipe->create_surface(pipe, resource, &surf_tmpl);
545   }
546   strb->surface = *psurf;
547}
548
549
550/**
551 * Return the pipe_resource which stores a particular texture image.
552 */
553static struct pipe_resource *
554get_teximage_resource(struct gl_texture_object *texObj,
555                      unsigned face, unsigned level)
556{
557   struct st_texture_image *stImg =
558      st_texture_image(texObj->Image[face][level]);
559
560   return stImg->pt;
561}
562
563
564/**
565 * Called by ctx->Driver.RenderTexture
566 */
567static void
568st_render_texture(struct gl_context *ctx,
569                  struct gl_framebuffer *fb,
570                  struct gl_renderbuffer_attachment *att)
571{
572   struct st_context *st = st_context(ctx);
573   struct gl_renderbuffer *rb = att->Renderbuffer;
574   struct st_renderbuffer *strb = st_renderbuffer(rb);
575   struct pipe_resource *pt;
576
577   pt = get_teximage_resource(att->Texture,
578                              att->CubeMapFace,
579                              att->TextureLevel);
580   assert(pt);
581
582   /* point renderbuffer at texobject */
583   strb->is_rtt = TRUE;
584   strb->rtt_face = att->CubeMapFace;
585   strb->rtt_slice = att->Zoffset;
586   strb->rtt_layered = att->Layered;
587   strb->rtt_nr_samples = att->NumSamples;
588   pipe_resource_reference(&strb->texture, pt);
589
590   st_update_renderbuffer_surface(st, strb);
591
592   /* Invalidate buffer state so that the pipe's framebuffer state
593    * gets updated.
594    * That's where the new renderbuffer (which we just created) gets
595    * passed to the pipe as a (color/depth) render target.
596    */
597   st_invalidate_buffers(st);
598
599
600   /* Need to trigger a call to update_framebuffer() since we just
601    * attached a new renderbuffer.
602    */
603   ctx->NewState |= _NEW_BUFFERS;
604}
605
606
607/**
608 * Called via ctx->Driver.FinishRenderTexture.
609 */
610static void
611st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
612{
613   struct st_context *st = st_context(ctx);
614   struct st_renderbuffer *strb = st_renderbuffer(rb);
615
616   if (!strb)
617      return;
618
619   strb->is_rtt = FALSE;
620
621   /* restore previous framebuffer state */
622   st_invalidate_buffers(st);
623}
624
625
626/** Debug helper */
627static void
628st_fbo_invalid(const char *reason)
629{
630   if (MESA_DEBUG_FLAGS & DEBUG_INCOMPLETE_FBO) {
631      _mesa_debug(NULL, "Invalid FBO: %s\n", reason);
632   }
633}
634
635
636/**
637 * Validate a renderbuffer attachment for a particular set of bindings.
638 */
639static GLboolean
640st_validate_attachment(struct gl_context *ctx,
641                       struct pipe_screen *screen,
642                       const struct gl_renderbuffer_attachment *att,
643                       unsigned bindings)
644{
645   const struct st_texture_object *stObj = st_texture_object(att->Texture);
646   enum pipe_format format;
647   mesa_format texFormat;
648   GLboolean valid;
649
650   /* Sanity check: we must be binding the surface as a (color) render target
651    * or depth/stencil target.
652    */
653   assert(bindings == PIPE_BIND_RENDER_TARGET ||
654          bindings == PIPE_BIND_DEPTH_STENCIL);
655
656   /* Only validate texture attachments for now, since
657    * st_renderbuffer_alloc_storage makes sure that
658    * the format is supported.
659    */
660   if (att->Type != GL_TEXTURE)
661      return GL_TRUE;
662
663   if (!stObj || !stObj->pt)
664      return GL_FALSE;
665
666   format = stObj->pt->format;
667   texFormat = att->Renderbuffer->TexImage->TexFormat;
668
669   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
670    * check for linear format support instead.
671    * Later when we create a surface, we change the format to a linear one. */
672   if (!ctx->Extensions.EXT_sRGB &&
673       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
674      const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
675      format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat);
676   }
677
678   valid = screen->is_format_supported(screen, format,
679                                       PIPE_TEXTURE_2D,
680                                       stObj->pt->nr_samples,
681                                       stObj->pt->nr_storage_samples,
682                                       bindings);
683   if (!valid) {
684      st_fbo_invalid("Invalid format");
685   }
686
687   return valid;
688}
689
690
691/**
692 * Check that the framebuffer configuration is valid in terms of what
693 * the driver can support.
694 *
695 * For Gallium we only supports combined Z+stencil, not separate buffers.
696 */
697static void
698st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
699{
700   struct st_context *st = st_context(ctx);
701   struct pipe_screen *screen = st->pipe->screen;
702   const struct gl_renderbuffer_attachment *depth =
703         &fb->Attachment[BUFFER_DEPTH];
704   const struct gl_renderbuffer_attachment *stencil =
705         &fb->Attachment[BUFFER_STENCIL];
706   GLuint i;
707   enum pipe_format first_format = PIPE_FORMAT_NONE;
708   boolean mixed_formats =
709         screen->get_param(screen, PIPE_CAP_MIXED_COLORBUFFER_FORMATS) != 0;
710
711   if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
712      st_fbo_invalid("Different Depth/Stencil buffer formats");
713      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
714      return;
715   }
716   if (depth->Type == GL_RENDERBUFFER_EXT &&
717       stencil->Type == GL_RENDERBUFFER_EXT &&
718       depth->Renderbuffer != stencil->Renderbuffer) {
719      st_fbo_invalid("Separate Depth/Stencil buffers");
720      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
721      return;
722   }
723   if (depth->Type == GL_TEXTURE &&
724       stencil->Type == GL_TEXTURE &&
725       depth->Texture != stencil->Texture) {
726      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
727      st_fbo_invalid("Different Depth/Stencil textures");
728      return;
729   }
730
731   if (!st_validate_attachment(ctx, screen, depth, PIPE_BIND_DEPTH_STENCIL)) {
732      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
733      st_fbo_invalid("Invalid depth attachment");
734      return;
735   }
736   if (!st_validate_attachment(ctx, screen, stencil, PIPE_BIND_DEPTH_STENCIL)) {
737      fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
738      st_fbo_invalid("Invalid stencil attachment");
739      return;
740   }
741   for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
742      struct gl_renderbuffer_attachment *att =
743            &fb->Attachment[BUFFER_COLOR0 + i];
744      enum pipe_format format;
745
746      if (!st_validate_attachment(ctx, screen, att, PIPE_BIND_RENDER_TARGET)) {
747         fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
748         st_fbo_invalid("Invalid color attachment");
749         return;
750      }
751
752      if (!mixed_formats) {
753         /* Disallow mixed formats. */
754         if (att->Type != GL_NONE) {
755            format = st_renderbuffer(att->Renderbuffer)->surface->format;
756         } else {
757            continue;
758         }
759
760         if (first_format == PIPE_FORMAT_NONE) {
761            first_format = format;
762         } else if (format != first_format) {
763            fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
764            st_fbo_invalid("Mixed color formats");
765            return;
766         }
767      }
768   }
769}
770
771
772/**
773 * Called by ctx->Driver.DiscardFramebuffer
774 */
775static void
776st_discard_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb,
777                       struct gl_renderbuffer_attachment *att)
778{
779   struct st_context *st = st_context(ctx);
780   struct pipe_resource *prsc;
781
782   if (!att->Renderbuffer)
783      return;
784
785   prsc = st_renderbuffer(att->Renderbuffer)->surface->texture;
786
787   /* using invalidate_resource will only work for simple 2D resources */
788   if (prsc->depth0 != 1 || prsc->array_size != 1 || prsc->last_level != 0)
789      return;
790
791   if (st->pipe->invalidate_resource)
792      st->pipe->invalidate_resource(st->pipe, prsc);
793}
794
795
796/**
797 * Called via glDrawBuffer.  We only provide this driver function so that we
798 * can check if we need to allocate a new renderbuffer.  Specifically, we
799 * don't usually allocate a front color buffer when using a double-buffered
800 * visual.  But if the app calls glDrawBuffer(GL_FRONT) we need to allocate
801 * that buffer.  Note, this is only for window system buffers, not user-
802 * created FBOs.
803 */
804static void
805st_DrawBufferAllocate(struct gl_context *ctx)
806{
807   struct st_context *st = st_context(ctx);
808   struct gl_framebuffer *fb = ctx->DrawBuffer;
809
810   if (_mesa_is_winsys_fbo(fb)) {
811      GLuint i;
812      /* add the renderbuffers on demand */
813      for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
814         gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
815
816         if (idx != BUFFER_NONE) {
817            st_manager_add_color_renderbuffer(st, fb, idx);
818         }
819      }
820   }
821}
822
823
824/**
825 * Called via glReadBuffer.  As with st_DrawBufferAllocate, we use this
826 * function to check if we need to allocate a renderbuffer on demand.
827 */
828static void
829st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
830{
831   struct st_context *st = st_context(ctx);
832   struct gl_framebuffer *fb = ctx->ReadBuffer;
833
834   (void) buffer;
835
836   /* Check if we need to allocate a front color buffer.
837    * Front buffers are often allocated on demand (other color buffers are
838    * always allocated in advance).
839    */
840   if ((fb->_ColorReadBufferIndex == BUFFER_FRONT_LEFT ||
841        fb->_ColorReadBufferIndex == BUFFER_FRONT_RIGHT) &&
842       fb->Attachment[fb->_ColorReadBufferIndex].Type == GL_NONE) {
843      assert(_mesa_is_winsys_fbo(fb));
844      /* add the buffer */
845      st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
846      _mesa_update_state(ctx);
847      st_validate_state(st, ST_PIPELINE_UPDATE_FRAMEBUFFER);
848   }
849}
850
851
852
853/**
854 * Called via ctx->Driver.MapRenderbuffer.
855 */
856static void
857st_MapRenderbuffer(struct gl_context *ctx,
858                   struct gl_renderbuffer *rb,
859                   GLuint x, GLuint y, GLuint w, GLuint h,
860                   GLbitfield mode,
861                   GLubyte **mapOut, GLint *rowStrideOut,
862                   bool flip_y)
863{
864   struct st_context *st = st_context(ctx);
865   struct st_renderbuffer *strb = st_renderbuffer(rb);
866   struct pipe_context *pipe = st->pipe;
867   const GLboolean invert = rb->Name == 0;
868   GLuint y2;
869   GLubyte *map;
870
871   /* driver does not support GL_FRAMEBUFFER_FLIP_Y_MESA */
872   assert((rb->Name == 0) == flip_y);
873
874   if (strb->software) {
875      /* software-allocated renderbuffer (probably an accum buffer) */
876      if (strb->data) {
877         GLint bpp = _mesa_get_format_bytes(strb->Base.Format);
878         GLint stride = _mesa_format_row_stride(strb->Base.Format,
879                                                strb->Base.Width);
880         *mapOut = (GLubyte *) strb->data + y * stride + x * bpp;
881         *rowStrideOut = stride;
882      }
883      else {
884         *mapOut = NULL;
885         *rowStrideOut = 0;
886      }
887      return;
888   }
889
890   /* Check for unexpected flags */
891   assert((mode & ~(GL_MAP_READ_BIT |
892                    GL_MAP_WRITE_BIT |
893                    GL_MAP_INVALIDATE_RANGE_BIT)) == 0);
894
895   const enum pipe_transfer_usage transfer_flags =
896      st_access_flags_to_transfer_flags(mode, false);
897
898   /* Note: y=0=bottom of buffer while y2=0=top of buffer.
899    * 'invert' will be true for window-system buffers and false for
900    * user-allocated renderbuffers and textures.
901    */
902   if (invert)
903      y2 = strb->Base.Height - y - h;
904   else
905      y2 = y;
906
907    map = pipe_transfer_map(pipe,
908                            strb->texture,
909                            strb->surface->u.tex.level,
910                            strb->surface->u.tex.first_layer,
911                            transfer_flags, x, y2, w, h, &strb->transfer);
912   if (map) {
913      if (invert) {
914         *rowStrideOut = -(int) strb->transfer->stride;
915         map += (h - 1) * strb->transfer->stride;
916      }
917      else {
918         *rowStrideOut = strb->transfer->stride;
919      }
920      *mapOut = map;
921   }
922   else {
923      *mapOut = NULL;
924      *rowStrideOut = 0;
925   }
926}
927
928
929/**
930 * Called via ctx->Driver.UnmapRenderbuffer.
931 */
932static void
933st_UnmapRenderbuffer(struct gl_context *ctx,
934                     struct gl_renderbuffer *rb)
935{
936   struct st_context *st = st_context(ctx);
937   struct st_renderbuffer *strb = st_renderbuffer(rb);
938   struct pipe_context *pipe = st->pipe;
939
940   if (strb->software) {
941      /* software-allocated renderbuffer (probably an accum buffer) */
942      return;
943   }
944
945   pipe_transfer_unmap(pipe, strb->transfer);
946   strb->transfer = NULL;
947}
948
949
950/**
951 * Called via ctx->Driver.EvaluateDepthValues.
952 */
953static void
954st_EvaluateDepthValues(struct gl_context *ctx)
955{
956   struct st_context *st = st_context(ctx);
957
958   st_validate_state(st, ST_PIPELINE_UPDATE_FRAMEBUFFER);
959
960   st->pipe->evaluate_depth_buffer(st->pipe);
961}
962
963
964void
965st_init_fbo_functions(struct dd_function_table *functions)
966{
967   functions->NewFramebuffer = _mesa_new_framebuffer;
968   functions->NewRenderbuffer = st_new_renderbuffer;
969   functions->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw;
970   functions->RenderTexture = st_render_texture;
971   functions->FinishRenderTexture = st_finish_render_texture;
972   functions->ValidateFramebuffer = st_validate_framebuffer;
973   functions->DiscardFramebuffer = st_discard_framebuffer;
974
975   functions->DrawBufferAllocate = st_DrawBufferAllocate;
976   functions->ReadBuffer = st_ReadBuffer;
977
978   functions->MapRenderbuffer = st_MapRenderbuffer;
979   functions->UnmapRenderbuffer = st_UnmapRenderbuffer;
980   functions->EvaluateDepthValues = st_EvaluateDepthValues;
981}
982