Esempio n. 1
0
/**
 * Initialize the texture image's FetchTexel methods.
 */
static void
set_fetch_functions(struct swrast_texture_image *texImage, GLuint dims)
{
   gl_format format = texImage->Base.TexFormat;

   ASSERT(dims == 1 || dims == 2 || dims == 3);

   if (texImage->Base.TexObject->Sampler.sRGBDecode == GL_SKIP_DECODE_EXT &&
       _mesa_get_format_color_encoding(format) == GL_SRGB) {
      format = _mesa_get_srgb_format_linear(format);
   }

   texImage->FetchTexel = _mesa_get_texel_fetch_func(format, dims);
   ASSERT(texImage->FetchTexel);
}
Esempio n. 2
0
/**
 * Validate a renderbuffer attachment for a particular set of bindings.
 */
static GLboolean
st_validate_attachment(struct gl_context *ctx,
		       struct pipe_screen *screen,
		       const struct gl_renderbuffer_attachment *att,
		       unsigned bindings)
{
   const struct st_texture_object *stObj = st_texture_object(att->Texture);
   enum pipe_format format;
   mesa_format texFormat;
   GLboolean valid;

   /* Sanity check: we must be binding the surface as a (color) render target
    * or depth/stencil target.
    */
   assert(bindings == PIPE_BIND_RENDER_TARGET ||
          bindings == PIPE_BIND_DEPTH_STENCIL);

   /* Only validate texture attachments for now, since
    * st_renderbuffer_alloc_storage makes sure that
    * the format is supported.
    */
   if (att->Type != GL_TEXTURE)
      return GL_TRUE;

   if (!stObj || !stObj->pt)
      return GL_FALSE;

   format = stObj->pt->format;
   texFormat = att->Renderbuffer->TexImage->TexFormat;

   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
    * check for linear format support instead.
    * Later when we create a surface, we change the format to a linear one. */
   if (!ctx->Extensions.EXT_framebuffer_sRGB &&
       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
      const mesa_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
      format = st_mesa_format_to_pipe_format(st_context(ctx), linearFormat);
   }

   valid = screen->is_format_supported(screen, format,
                                      PIPE_TEXTURE_2D,
                                      stObj->pt->nr_samples, bindings);
   if (!valid) {
      st_fbo_invalid("Invalid format");
   }

   return valid;
}
/**
 * Validate a renderbuffer attachment for a particular set of bindings.
 */
static GLboolean
st_validate_attachment(struct gl_context *ctx,
		       struct pipe_screen *screen,
		       const struct gl_renderbuffer_attachment *att,
		       unsigned bindings)
{
   const struct st_texture_object *stObj = st_texture_object(att->Texture);
   enum pipe_format format;
   gl_format texFormat;
   GLboolean valid;

   /* Only validate texture attachments for now, since
    * st_renderbuffer_alloc_storage makes sure that
    * the format is supported.
    */
   if (att->Type != GL_TEXTURE)
      return GL_TRUE;

   if (!stObj)
      return GL_FALSE;

   format = stObj->pt->format;
   texFormat = _mesa_get_attachment_teximage_const(att)->TexFormat;

   /* If the encoding is sRGB and sRGB rendering cannot be enabled,
    * check for linear format support instead.
    * Later when we create a surface, we change the format to a linear one. */
   if (!ctx->Extensions.EXT_framebuffer_sRGB &&
       _mesa_get_format_color_encoding(texFormat) == GL_SRGB) {
      const gl_format linearFormat = _mesa_get_srgb_format_linear(texFormat);
      format = st_mesa_format_to_pipe_format(linearFormat);
   }

   valid = screen->is_format_supported(screen, format,
                                      PIPE_TEXTURE_2D,
                                      stObj->pt->nr_samples, bindings);
   if (!valid) {
      st_fbo_invalid("Invalid format");
   }

   return valid;
}
Esempio n. 4
0
/**
 * Initialize the texture image's FetchTexel methods.
 */
static void
set_fetch_functions(const struct gl_sampler_object *samp,
                    struct swrast_texture_image *texImage, GLuint dims)
{
   gl_format format = texImage->Base.TexFormat;

#ifdef DEBUG
   /* check that the table entries are sorted by format name */
   gl_format fmt;
   for (fmt = 0; fmt < MESA_FORMAT_COUNT; fmt++) {
      assert(texfetch_funcs[fmt].Name == fmt);
   }
#endif

   STATIC_ASSERT(Elements(texfetch_funcs) == MESA_FORMAT_COUNT);

   if (samp->sRGBDecode == GL_SKIP_DECODE_EXT &&
       _mesa_get_format_color_encoding(format) == GL_SRGB) {
      format = _mesa_get_srgb_format_linear(format);
   }

   assert(format < MESA_FORMAT_COUNT);

   switch (dims) {
   case 1:
      texImage->FetchTexel = texfetch_funcs[format].Fetch1D;
      break;
   case 2:
      texImage->FetchTexel = texfetch_funcs[format].Fetch2D;
      break;
   case 3:
      texImage->FetchTexel = texfetch_funcs[format].Fetch3D;
      break;
   default:
      assert(!"Bad dims in set_fetch_functions()");
   }

   texImage->FetchCompressedTexel = _mesa_get_compressed_fetch_func(format);

   ASSERT(texImage->FetchTexel);
}
Esempio n. 5
0
/**
 * Note: if the src (or dst) is a 2D multisample array texture on Gen7+ using
 * INTEL_MSAA_LAYOUT_UMS or INTEL_MSAA_LAYOUT_CMS, src_layer (dst_layer) is
 * the physical layer holding sample 0.  So, for example, if
 * src_mt->num_samples == 4, then logical layer n corresponds to src_layer ==
 * 4*n.
 */
void
brw_blorp_blit_miptrees(struct brw_context *brw,
                        struct intel_mipmap_tree *src_mt,
                        unsigned src_level, unsigned src_layer,
                        mesa_format src_format, int src_swizzle,
                        struct intel_mipmap_tree *dst_mt,
                        unsigned dst_level, unsigned dst_layer,
                        mesa_format dst_format,
                        float src_x0, float src_y0,
                        float src_x1, float src_y1,
                        float dst_x0, float dst_y0,
                        float dst_x1, float dst_y1,
                        GLenum filter, bool mirror_x, bool mirror_y,
                        bool decode_srgb, bool encode_srgb)
{
   /* Blorp operates in logical layers */
   src_layer = physical_to_logical_layer(src_mt, src_layer);
   dst_layer = physical_to_logical_layer(dst_mt, dst_layer);

   DBG("%s from %dx %s mt %p %d %d (%f,%f) (%f,%f)"
       "to %dx %s mt %p %d %d (%f,%f) (%f,%f) (flip %d,%d)\n",
       __func__,
       src_mt->num_samples, _mesa_get_format_name(src_mt->format), src_mt,
       src_level, src_layer, src_x0, src_y0, src_x1, src_y1,
       dst_mt->num_samples, _mesa_get_format_name(dst_mt->format), dst_mt,
       dst_level, dst_layer, dst_x0, dst_y0, dst_x1, dst_y1,
       mirror_x, mirror_y);

   if (!decode_srgb && _mesa_get_format_color_encoding(src_format) == GL_SRGB)
      src_format = _mesa_get_srgb_format_linear(src_format);

   if (!encode_srgb && _mesa_get_format_color_encoding(dst_format) == GL_SRGB)
      dst_format = _mesa_get_srgb_format_linear(dst_format);

   /* When doing a multisample resolve of a GL_LUMINANCE32F or GL_INTENSITY32F
    * texture, the above code configures the source format for L32_FLOAT or
    * I32_FLOAT, and the destination format for R32_FLOAT.  On Sandy Bridge,
    * the SAMPLE message appears to handle multisampled L32_FLOAT and
    * I32_FLOAT textures incorrectly, resulting in blocky artifacts.  So work
    * around the problem by using a source format of R32_FLOAT.  This
    * shouldn't affect rendering correctness, since the destination format is
    * R32_FLOAT, so only the contents of the red channel matters.
    */
   if (brw->gen == 6 &&
       src_mt->num_samples > 1 && dst_mt->num_samples <= 1 &&
       src_mt->format == dst_mt->format &&
       (dst_format == MESA_FORMAT_L_FLOAT32 ||
        dst_format == MESA_FORMAT_I_FLOAT32)) {
      src_format = dst_format = MESA_FORMAT_R_FLOAT32;
   }

   uint32_t src_usage_flags = (1 << ISL_AUX_USAGE_MCS);
   if (src_format == src_mt->format)
      src_usage_flags |= (1 << ISL_AUX_USAGE_CCS_E);

   uint32_t dst_usage_flags = (1 << ISL_AUX_USAGE_MCS);
   if (dst_format == dst_mt->format) {
      dst_usage_flags |= (1 << ISL_AUX_USAGE_CCS_E) |
                         (1 << ISL_AUX_USAGE_CCS_D);
   }

   struct isl_surf tmp_surfs[4];
   struct blorp_surf src_surf, dst_surf;
   blorp_surf_for_miptree(brw, &src_surf, src_mt, false, src_usage_flags,
                          &src_level, src_layer, 1, &tmp_surfs[0]);
   blorp_surf_for_miptree(brw, &dst_surf, dst_mt, true, dst_usage_flags,
                          &dst_level, dst_layer, 1, &tmp_surfs[2]);

   struct isl_swizzle src_isl_swizzle = {
      .r = swizzle_to_scs(GET_SWZ(src_swizzle, 0)),
      .g = swizzle_to_scs(GET_SWZ(src_swizzle, 1)),
      .b = swizzle_to_scs(GET_SWZ(src_swizzle, 2)),
      .a = swizzle_to_scs(GET_SWZ(src_swizzle, 3)),
   };

   struct blorp_batch batch;
   blorp_batch_init(&brw->blorp, &batch, brw, 0);
   blorp_blit(&batch, &src_surf, src_level, src_layer,
              brw_blorp_to_isl_format(brw, src_format, false), src_isl_swizzle,
              &dst_surf, dst_level, dst_layer,
              brw_blorp_to_isl_format(brw, dst_format, true),
              ISL_SWIZZLE_IDENTITY,
              src_x0, src_y0, src_x1, src_y1,
              dst_x0, dst_y0, dst_x1, dst_y1,
              filter, mirror_x, mirror_y);
   blorp_batch_finish(&batch);
}

void
brw_blorp_copy_miptrees(struct brw_context *brw,
                        struct intel_mipmap_tree *src_mt,
                        unsigned src_level, unsigned src_layer,
                        struct intel_mipmap_tree *dst_mt,
                        unsigned dst_level, unsigned dst_layer,
                        unsigned src_x, unsigned src_y,
                        unsigned dst_x, unsigned dst_y,
                        unsigned src_width, unsigned src_height)
{
   DBG("%s from %dx %s mt %p %d %d (%d,%d) %dx%d"
       "to %dx %s mt %p %d %d (%d,%d)\n",
       __func__,
       src_mt->num_samples, _mesa_get_format_name(src_mt->format), src_mt,
       src_level, src_layer, src_x, src_y, src_width, src_height,
       dst_mt->num_samples, _mesa_get_format_name(dst_mt->format), dst_mt,
       dst_level, dst_layer, dst_x, dst_y);

   struct isl_surf tmp_surfs[4];
   struct blorp_surf src_surf, dst_surf;
   blorp_surf_for_miptree(brw, &src_surf, src_mt, false,
                          (1 << ISL_AUX_USAGE_MCS) |
                          (1 << ISL_AUX_USAGE_CCS_E),
                          &src_level, src_layer, 1, &tmp_surfs[0]);
   blorp_surf_for_miptree(brw, &dst_surf, dst_mt, true,
                          (1 << ISL_AUX_USAGE_MCS) |
                          (1 << ISL_AUX_USAGE_CCS_E),
                          &dst_level, dst_layer, 1, &tmp_surfs[2]);

   struct blorp_batch batch;
   blorp_batch_init(&brw->blorp, &batch, brw, 0);
   blorp_copy(&batch, &src_surf, src_level, src_layer,
              &dst_surf, dst_level, dst_layer,
              src_x, src_y, dst_x, dst_y, src_width, src_height);
   blorp_batch_finish(&batch);
}
Esempio n. 6
0
/**
 * Check if the call to _mesa_meta_GenerateMipmap() will require a
 * software fallback.  The fallback path will require that the texture
 * images are mapped.
 * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
 */
static bool
fallback_required(struct gl_context *ctx, GLenum target,
                  struct gl_texture_object *texObj)
{
   const GLuint fboSave = ctx->DrawBuffer->Name;
   struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
   struct gl_texture_image *baseImage;
   GLuint srcLevel;
   GLenum status;

   /* check for fallbacks */
//   if (target == GL_TEXTURE_3D) {
//      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
//                       "glGenerateMipmap() to %s target\n",
//                       _mesa_lookup_enum_by_nr(target));
//      return true;
//   }

   srcLevel = texObj->BaseLevel;
   baseImage = _mesa_select_tex_image(texObj, target, srcLevel);
   if (!baseImage) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() couldn't find base teximage\n");
      return true;
   }

   if (_mesa_is_format_compressed(baseImage->TexFormat)) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() with %s format\n",
                       _mesa_get_format_name(baseImage->TexFormat));
      return true;
   }

   if (_mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB &&
       !ctx->Extensions.EXT_texture_sRGB_decode) {
      /* The texture format is sRGB but we can't turn off sRGB->linear
       * texture sample conversion.  So we won't be able to generate the
       * right colors when rendering.  Need to use a fallback.
       */
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() of sRGB texture without "
                       "sRGB decode\n");
      return true;
   }

   /*
    * Test that we can actually render in the texture's format.
    */
   if (!mipmap->FBO)
      glGenFramebuffers(1, &mipmap->FBO);
   glBindFramebuffer(GL_FRAMEBUFFER, mipmap->FBO);

   _mesa_meta_bind_fbo_image(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, baseImage, 0);

   status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

   glBindFramebuffer(GL_FRAMEBUFFER, fboSave);

   if (status != GL_FRAMEBUFFER_COMPLETE) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() got incomplete FBO\n");
      return true;
   }

   return false;
}
/**
 * The glGet queries of the framebuffer red/green/blue size, stencil size,
 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
 * change depending on the renderbuffer bindings.  This function updates
 * the given framebuffer's Visual from the current renderbuffer bindings.
 *
 * This may apply to user-created framebuffers or window system framebuffers.
 *
 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
 * The former one is used to convert floating point depth values into
 * integer Z values.
 */
void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
				struct gl_framebuffer *fb)
{
   GLuint i;

   memset(&fb->Visual, 0, sizeof(fb->Visual));
   fb->Visual.rgbMode = GL_TRUE; /* assume this */

   /* find first RGB renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
         const mesa_format fmt = rb->Format;

         /* Grab samples and sampleBuffers from any attachment point (assuming
          * the framebuffer is complete, we'll get the same answer from all
          * attachments).
          */
         fb->Visual.samples = rb->NumSamples;
         fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0;

         if (_mesa_is_legal_color_format(ctx, baseFormat)) {
            fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
            fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
            fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
            fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
            fb->Visual.rgbBits = fb->Visual.redBits
               + fb->Visual.greenBits + fb->Visual.blueBits;
            if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
                fb->Visual.sRGBCapable = ctx->Extensions.EXT_framebuffer_sRGB;
            break;
         }
      }
   }

   fb->Visual.floatMode = GL_FALSE;
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const mesa_format fmt = rb->Format;

         if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
            fb->Visual.floatMode = GL_TRUE;
            break;
         }
      }
   }

   if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_DEPTH].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveDepthBuffer = GL_TRUE;
      fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
   }

   if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_STENCIL].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveStencilBuffer = GL_TRUE;
      fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
   }

   if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_ACCUM].Renderbuffer;
      const mesa_format fmt = rb->Format;
      fb->Visual.haveAccumBuffer = GL_TRUE;
      fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
      fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
      fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
      fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
   }

   compute_depth_max(fb);
}
Esempio n. 8
0
/**
 * Create or update the pipe_surface of a FBO renderbuffer.
 * This is usually called after st_finalize_texture.
 */
void
st_update_renderbuffer_surface(struct st_context *st,
                               struct st_renderbuffer *strb)
{
   struct pipe_context *pipe = st->pipe;
   struct pipe_resource *resource = strb->texture;
   int rtt_width = strb->Base.Width;
   int rtt_height = strb->Base.Height;
   int rtt_depth = strb->Base.Depth;
   /*
    * For winsys fbo, it is possible that the renderbuffer is sRGB-capable but
    * the format of strb->texture is linear (because we have no control over
    * the format).  Check strb->Base.Format instead of strb->texture->format
    * to determine if the rb is sRGB-capable.
    */
   boolean enable_srgb = (st->ctx->Color.sRGBEnabled &&
         _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB);
   enum pipe_format format = (enable_srgb) ?
      util_format_srgb(resource->format) :
      util_format_linear(resource->format);
   unsigned first_layer, last_layer, level;

   if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
      rtt_depth = rtt_height;
      rtt_height = 1;
   }

   /* find matching mipmap level size */
   for (level = 0; level <= resource->last_level; level++) {
      if (u_minify(resource->width0, level) == rtt_width &&
          u_minify(resource->height0, level) == rtt_height &&
          (resource->target != PIPE_TEXTURE_3D ||
           u_minify(resource->depth0, level) == rtt_depth)) {
         break;
      }
   }
   assert(level <= resource->last_level);

   /* determine the layer bounds */
   if (strb->rtt_layered) {
      first_layer = 0;
      last_layer = util_max_layer(strb->texture, level);
   }
   else {
      first_layer =
      last_layer = strb->rtt_face + strb->rtt_slice;
   }

   if (!strb->surface ||
       strb->surface->texture->nr_samples != strb->Base.NumSamples ||
       strb->surface->format != format ||
       strb->surface->texture != resource ||
       strb->surface->width != rtt_width ||
       strb->surface->height != rtt_height ||
       strb->surface->u.tex.level != level ||
       strb->surface->u.tex.first_layer != first_layer ||
       strb->surface->u.tex.last_layer != last_layer) {
      /* create a new pipe_surface */
      struct pipe_surface surf_tmpl;
      memset(&surf_tmpl, 0, sizeof(surf_tmpl));
      surf_tmpl.format = format;
      surf_tmpl.u.tex.level = level;
      surf_tmpl.u.tex.first_layer = first_layer;
      surf_tmpl.u.tex.last_layer = last_layer;

      pipe_surface_reference(&strb->surface, NULL);

      strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl);
   }
}
/**
 * Update framebuffer state (color, depth, stencil, etc. buffers)
 */
void
st_update_framebuffer_state( struct st_context *st )
{
   struct pipe_framebuffer_state framebuffer;
   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
   struct st_renderbuffer *strb;
   GLuint i;

   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   st->state.fb_orientation = st_fb_orientation(fb);

   /**
    * Quantize the derived default number of samples:
    *
    * A query to the driver of supported MSAA values the
    * hardware supports is done as to legalize the number
    * of application requested samples, NumSamples.
    * See commit eb9cf3c for more information.
    */
   fb->DefaultGeometry._NumSamples =
      framebuffer_quantize_num_samples(st, fb->DefaultGeometry.NumSamples);

   framebuffer.width  = _mesa_geometric_width(fb);
   framebuffer.height = _mesa_geometric_height(fb);
   framebuffer.samples = _mesa_geometric_samples(fb);
   framebuffer.layers = _mesa_geometric_layers(fb);

   /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
    * to determine which surfaces to draw to
    */
   framebuffer.nr_cbufs = fb->_NumColorDrawBuffers;

   for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
      framebuffer.cbufs[i] = NULL;
      strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);

      if (strb) {
         if (strb->is_rtt || (strb->texture &&
             _mesa_get_format_color_encoding(strb->Base.Format) == GL_SRGB)) {
            /* rendering to a GL texture, may have to update surface */
            st_update_renderbuffer_surface(st, strb);
         }

         if (strb->surface) {
            framebuffer.cbufs[i] = strb->surface;
            update_framebuffer_size(&framebuffer, strb->surface);
         }
         strb->defined = GL_TRUE; /* we'll be drawing something */
      }
   }

   for (i = framebuffer.nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
      framebuffer.cbufs[i] = NULL;
   }

   /* Remove trailing GL_NONE draw buffers. */
   while (framebuffer.nr_cbufs &&
          !framebuffer.cbufs[framebuffer.nr_cbufs-1]) {
      framebuffer.nr_cbufs--;
   }

   /*
    * Depth/Stencil renderbuffer/surface.
    */
   strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
   if (!strb)
      strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);

   if (strb) {
      if (strb->is_rtt) {
         /* rendering to a GL texture, may have to update surface */
         st_update_renderbuffer_surface(st, strb);
      }
      framebuffer.zsbuf = strb->surface;
      update_framebuffer_size(&framebuffer, strb->surface);
   }
   else
      framebuffer.zsbuf = NULL;

#ifdef DEBUG
   /* Make sure the resource binding flags were set properly */
   for (i = 0; i < framebuffer.nr_cbufs; i++) {
      assert(!framebuffer.cbufs[i] ||
             framebuffer.cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
   }
   if (framebuffer.zsbuf) {
      assert(framebuffer.zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
   }
#endif

   if (framebuffer.width == USHRT_MAX)
      framebuffer.width = 0;
   if (framebuffer.height == USHRT_MAX)
      framebuffer.height = 0;

   cso_set_framebuffer(st->cso_context, &framebuffer);

   st->state.fb_width = framebuffer.width;
   st->state.fb_height = framebuffer.height;
   st->state.fb_num_samples = util_framebuffer_get_num_samples(&framebuffer);
   st->state.fb_num_layers = util_framebuffer_get_num_layers(&framebuffer);
   st->state.fb_num_cb = framebuffer.nr_cbufs;
}
Esempio n. 10
0
static bool
do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb,
                      struct gl_renderbuffer *rb, unsigned buf,
                      bool partial_clear, bool encode_srgb)
{
   struct gl_context *ctx = &brw->ctx;
   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
   mesa_format format = irb->mt->format;
   uint32_t x0, x1, y0, y1;

   if (!encode_srgb && _mesa_get_format_color_encoding(format) == GL_SRGB)
      format = _mesa_get_srgb_format_linear(format);

   x0 = fb->_Xmin;
   x1 = fb->_Xmax;
   if (rb->Name != 0) {
      y0 = fb->_Ymin;
      y1 = fb->_Ymax;
   } else {
      y0 = rb->Height - fb->_Ymax;
      y1 = rb->Height - fb->_Ymin;
   }

   /* If the clear region is empty, just return. */
   if (x0 == x1 || y0 == y1)
      return true;

   bool can_fast_clear = !partial_clear;

   bool color_write_disable[4] = { false, false, false, false };
   if (set_write_disables(irb, ctx->Color.ColorMask[buf], color_write_disable))
      can_fast_clear = false;

   if (irb->mt->no_ccs ||
       !brw_is_color_fast_clear_compatible(brw, irb->mt, &ctx->Color.ClearColor))
      can_fast_clear = false;

   const unsigned logical_layer = irb_logical_mt_layer(irb);
   const enum intel_fast_clear_state fast_clear_state =
      intel_miptree_get_fast_clear_state(irb->mt, irb->mt_level,
                                         logical_layer);

   /* Surface state can only record one fast clear color value. Therefore
    * unless different levels/layers agree on the color it can be used to
    * represent only single level/layer. Here it will be reserved for the
    * first slice (level 0, layer 0).
    */
   if (irb->layer_count > 1 || irb->mt_level || irb->mt_layer)
      can_fast_clear = false;

   if (can_fast_clear) {
      union gl_color_union override_color =
         brw_meta_convert_fast_clear_color(brw, irb->mt,
                                           &ctx->Color.ClearColor);

      /* Record the clear color in the miptree so that it will be
       * programmed in SURFACE_STATE by later rendering and resolve
       * operations.
       */
      const bool color_updated = brw_meta_set_fast_clear_color(
                                    brw, &irb->mt->gen9_fast_clear_color,
                                    &override_color);

      /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the clear
       * is redundant and can be skipped.
       */
      if (!color_updated && fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR)
         return true;

      /* If the MCS buffer hasn't been allocated yet, we need to allocate
       * it now.
       */
      if (!irb->mt->mcs_buf) {
         assert(!intel_miptree_is_lossless_compressed(brw, irb->mt));
         if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt, false)) {
            /* MCS allocation failed--probably this will only happen in
             * out-of-memory conditions.  But in any case, try to recover
             * by falling back to a non-blorp clear technique.
             */
            return false;
         }
      }
   }

   const unsigned num_layers = fb->MaxNumLayers ? irb->layer_count : 1;

   /* We can't setup the blorp_surf until we've allocated the MCS above */
   struct isl_surf isl_tmp[2];
   struct blorp_surf surf;
   unsigned level = irb->mt_level;
   blorp_surf_for_miptree(brw, &surf, irb->mt, true,
                          (1 << ISL_AUX_USAGE_MCS) |
                          (1 << ISL_AUX_USAGE_CCS_E) |
                          (1 << ISL_AUX_USAGE_CCS_D),
                          &level, logical_layer, num_layers, isl_tmp);

   if (can_fast_clear) {
      DBG("%s (fast) to mt %p level %d layers %d+%d\n", __FUNCTION__,
          irb->mt, irb->mt_level, irb->mt_layer, num_layers);

      struct blorp_batch batch;
      blorp_batch_init(&brw->blorp, &batch, brw, 0);
      blorp_fast_clear(&batch, &surf,
                       (enum isl_format)brw->render_target_format[format],
                       level, logical_layer, num_layers,
                       x0, y0, x1, y1);
      blorp_batch_finish(&batch);

      /* Now that the fast clear has occurred, put the buffer in
       * INTEL_FAST_CLEAR_STATE_CLEAR so that we won't waste time doing
       * redundant clears.
       */
      intel_miptree_set_fast_clear_state(brw, irb->mt, irb->mt_level,
                                         logical_layer, num_layers,
                                         INTEL_FAST_CLEAR_STATE_CLEAR);
   } else {
      DBG("%s (slow) to mt %p level %d layer %d+%d\n", __FUNCTION__,
          irb->mt, irb->mt_level, irb->mt_layer, num_layers);

      union isl_color_value clear_color;
      memcpy(clear_color.f32, ctx->Color.ClearColor.f, sizeof(float) * 4);

      struct blorp_batch batch;
      blorp_batch_init(&brw->blorp, &batch, brw, 0);
      blorp_clear(&batch, &surf,
                  (enum isl_format)brw->render_target_format[format],
                  ISL_SWIZZLE_IDENTITY,
                  level, irb_logical_mt_layer(irb), num_layers,
                  x0, y0, x1, y1,
                  clear_color, color_write_disable);
      blorp_batch_finish(&batch);
   }

   return true;
}
Esempio n. 11
0
static bool
do_single_blorp_clear(struct brw_context *brw, struct gl_framebuffer *fb,
                      struct gl_renderbuffer *rb, unsigned buf,
                      bool partial_clear, bool encode_srgb, unsigned layer)
{
    struct gl_context *ctx = &brw->ctx;
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
    mesa_format format = irb->mt->format;

    struct brw_blorp_params params;
    brw_blorp_params_init(&params);

    if (!encode_srgb && _mesa_get_format_color_encoding(format) == GL_SRGB)
        format = _mesa_get_srgb_format_linear(format);

    brw_blorp_surface_info_init(brw, &params.dst, irb->mt, irb->mt_level,
                                layer, format, true);

    /* Override the surface format according to the context's sRGB rules. */
    params.dst.brw_surfaceformat = brw->render_target_format[format];

    params.x0 = fb->_Xmin;
    params.x1 = fb->_Xmax;
    if (rb->Name != 0) {
        params.y0 = fb->_Ymin;
        params.y1 = fb->_Ymax;
    } else {
        params.y0 = rb->Height - fb->_Ymax;
        params.y1 = rb->Height - fb->_Ymin;
    }

    memcpy(&params.wm_inputs, ctx->Color.ClearColor.f, sizeof(float) * 4);

    bool use_simd16_replicated_data = true;

    /* From the SNB PRM (Vol4_Part1):
     *
     *     "Replicated data (Message Type = 111) is only supported when
     *      accessing tiled memory.  Using this Message Type to access linear
     *      (untiled) memory is UNDEFINED."
     */
    if (irb->mt->tiling == I915_TILING_NONE)
        use_simd16_replicated_data = false;

    /* Constant color writes ignore everyting in blend and color calculator
     * state.  This is not documented.
     */
    if (set_write_disables(irb, ctx->Color.ColorMask[buf],
                           params.color_write_disable))
        use_simd16_replicated_data = false;

    if (irb->mt->fast_clear_state != INTEL_FAST_CLEAR_STATE_NO_MCS &&
            !partial_clear && use_simd16_replicated_data &&
            brw_is_color_fast_clear_compatible(brw, irb->mt,
                    &ctx->Color.ClearColor)) {
        memset(&params.wm_inputs, 0xff, 4*sizeof(float));
        params.fast_clear_op = GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE;

        brw_get_fast_clear_rect(brw, fb, irb->mt, &params.x0, &params.y0,
                                &params.x1, &params.y1);
    } else {
        brw_meta_get_buffer_rect(fb, &params.x0, &params.y0,
                                 &params.x1, &params.y1);
    }

    brw_blorp_params_get_clear_kernel(brw, &params, use_simd16_replicated_data);

    const bool is_fast_clear =
        params.fast_clear_op == GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE;
    if (is_fast_clear) {
        /* Record the clear color in the miptree so that it will be
         * programmed in SURFACE_STATE by later rendering and resolve
         * operations.
         */
        const bool color_updated = brw_meta_set_fast_clear_color(
                                       brw, irb->mt, &ctx->Color.ClearColor);

        /* If the buffer is already in INTEL_FAST_CLEAR_STATE_CLEAR, the clear
         * is redundant and can be skipped.
         */
        if (!color_updated &&
                irb->mt->fast_clear_state == INTEL_FAST_CLEAR_STATE_CLEAR)
            return true;

        /* If the MCS buffer hasn't been allocated yet, we need to allocate
         * it now.
         */
        if (!irb->mt->mcs_mt) {
            if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt)) {
                /* MCS allocation failed--probably this will only happen in
                 * out-of-memory conditions.  But in any case, try to recover
                 * by falling back to a non-blorp clear technique.
                 */
                return false;
            }
        }
    }

    const char *clear_type;
    if (is_fast_clear)
        clear_type = "fast";
    else if (use_simd16_replicated_data)
        clear_type = "replicated";
    else
        clear_type = "slow";

    DBG("%s (%s) to mt %p level %d layer %d\n", __FUNCTION__, clear_type,
        irb->mt, irb->mt_level, irb->mt_layer);

    brw_blorp_exec(brw, &params);

    if (is_fast_clear) {
        /* Now that the fast clear has occurred, put the buffer in
         * INTEL_FAST_CLEAR_STATE_CLEAR so that we won't waste time doing
         * redundant clears.
         */
        irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_CLEAR;
    } else if (intel_miptree_is_lossless_compressed(brw, irb->mt)) {
        /* Compressed buffers can be cleared also using normal rep-clear. In
         * such case they bahave such as if they were drawn using normal 3D
         * render pipeline, and we simply mark the mcs as dirty.
         */
        assert(partial_clear);
        irb->mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_UNRESOLVED;
    }

    return true;
}
/**
 * Try to do a color or depth glBlitFramebuffer using texturing.
 *
 * We can do this when the src renderbuffer is actually a texture, or when the
 * driver exposes BindRenderbufferTexImage().
 */
static bool
blitframebuffer_texture(struct gl_context *ctx,
                        const struct gl_framebuffer *readFb,
                        const struct gl_framebuffer *drawFb,
                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                        GLenum filter, GLint flipX, GLint flipY,
                        GLboolean glsl_version, GLboolean do_depth)
{
   int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex;
   const struct gl_renderbuffer_attachment *readAtt =
      &readFb->Attachment[att_index];
   struct blit_state *blit = &ctx->Meta->Blit;
   struct fb_tex_blit_state fb_tex_blit;
   const GLint dstX = MIN2(dstX0, dstX1);
   const GLint dstY = MIN2(dstY0, dstY1);
   const GLint dstW = abs(dstX1 - dstX0);
   const GLint dstH = abs(dstY1 - dstY0);
   const int srcW = abs(srcX1 - srcX0);
   const int srcH = abs(srcY1 - srcY0);
   bool scaled_blit = false;
   struct gl_texture_object *texObj;
   GLuint srcLevel;
   GLenum target;
   struct gl_renderbuffer *rb = readAtt->Renderbuffer;
   struct temp_texture *meta_temp_texture;

   if (rb->NumSamples && !ctx->Extensions.ARB_texture_multisample)
      return false;

   _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit);

   if (readAtt->Texture &&
       (readAtt->Texture->Target == GL_TEXTURE_2D ||
        readAtt->Texture->Target == GL_TEXTURE_RECTANGLE ||
        readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE ||
        readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) {
      /* If there's a texture attached of a type we can handle, then just use
       * it directly.
       */
      srcLevel = readAtt->TextureLevel;
      texObj = readAtt->Texture;
      target = texObj->Target;
   } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) {
      if (!_mesa_meta_bind_rb_as_tex_image(ctx, rb, &fb_tex_blit.tempTex,
                                           &texObj, &target))
         return false;

      srcLevel = 0;
      if (_mesa_is_winsys_fbo(readFb)) {
         GLint temp = srcY0;
         srcY0 = rb->Height - srcY1;
         srcY1 = rb->Height - temp;
         flipY = -flipY;
      }
   } else {
      GLenum tex_base_format;
      /* Fall back to doing a CopyTexSubImage to get the destination
       * renderbuffer into a texture.
       */
      if (ctx->Meta->Blit.no_ctsi_fallback)
         return false;

      if (rb->NumSamples > 1)
         return false;

      if (do_depth) {
         meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx);
         tex_base_format = GL_DEPTH_COMPONENT;
      } else {
         meta_temp_texture = _mesa_meta_get_temp_texture(ctx);
         tex_base_format =
            _mesa_base_tex_format(ctx, rb->InternalFormat);
      }

      srcLevel = 0;
      target = meta_temp_texture->Target;
      texObj = _mesa_lookup_texture(ctx, meta_temp_texture->TexObj);
      if (texObj == NULL) {
         return false;
      }

      _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture,
                                       srcX0, srcY0,
                                       srcW, srcH,
                                       tex_base_format,
                                       filter);


      srcX0 = 0;
      srcY0 = 0;
      srcX1 = srcW;
      srcY1 = srcH;
   }

   fb_tex_blit.baseLevelSave = texObj->BaseLevel;
   fb_tex_blit.maxLevelSave = texObj->MaxLevel;
   fb_tex_blit.stencilSamplingSave = texObj->StencilSampling;

   scaled_blit = dstW != srcW || dstH != srcH;

   if (glsl_version) {
      setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, filter, scaled_blit,
                                  do_depth);
   }
   else {
      _mesa_meta_setup_ff_tnl_for_blit(ctx,
                                       &ctx->Meta->Blit.VAO,
                                       &ctx->Meta->Blit.buf_obj,
                                       2);
   }

   /*
     printf("Blit from texture!\n");
     printf("  srcAtt %p  dstAtt %p\n", readAtt, drawAtt);
     printf("  srcTex %p  dstText %p\n", texObj, drawAtt->Texture);
   */

   fb_tex_blit.sampler = _mesa_meta_setup_sampler(ctx, texObj, target, filter,
                                                  srcLevel);

   /* Always do our blits with no net sRGB decode or encode.
    *
    * However, if both the src and dst can be srgb decode/encoded, enable them
    * so that we do any blending (from scaling or from MSAA resolves) in the
    * right colorspace.
    *
    * Our choice of not doing any net encode/decode is from the GL 3.0
    * specification:
    *
    *     "Blit operations bypass the fragment pipeline. The only fragment
    *      operations which affect a blit are the pixel ownership test and the
    *      scissor test."
    *
    * The GL 4.4 specification disagrees and says that the sRGB part of the
    * fragment pipeline applies, but this was found to break applications.
    */
   if (ctx->Extensions.EXT_texture_sRGB_decode) {
      if (_mesa_get_format_color_encoding(rb->Format) == GL_SRGB &&
          drawFb->Visual.sRGBCapable) {
         _mesa_SamplerParameteri(fb_tex_blit.sampler,
                                 GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
         _mesa_set_framebuffer_srgb(ctx, GL_TRUE);
      } else {
         _mesa_SamplerParameteri(fb_tex_blit.sampler,
                                 GL_TEXTURE_SRGB_DECODE_EXT,
                                 GL_SKIP_DECODE_EXT);
         /* set_framebuffer_srgb was set by _mesa_meta_begin(). */
      }
   }

   if (!glsl_version) {
      _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
      _mesa_set_enable(ctx, target, GL_TRUE);
   }

   /* Prepare vertex data (the VBO was previously created and bound) */
   {
      struct vertex verts[4];
      GLfloat s0, t0, s1, t1;

      if (target == GL_TEXTURE_2D) {
         const struct gl_texture_image *texImage
            = _mesa_select_tex_image(texObj, target, srcLevel);
         s0 = srcX0 / (float) texImage->Width;
         s1 = srcX1 / (float) texImage->Width;
         t0 = srcY0 / (float) texImage->Height;
         t1 = srcY1 / (float) texImage->Height;
      }
      else {
         assert(target == GL_TEXTURE_RECTANGLE_ARB ||
                target == GL_TEXTURE_2D_MULTISAMPLE ||
                target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
         s0 = (float) srcX0;
         s1 = (float) srcX1;
         t0 = (float) srcY0;
         t1 = (float) srcY1;
      }

      /* Silence valgrind warnings about reading uninitialized stack. */
      memset(verts, 0, sizeof(verts));

      /* setup vertex positions */
      verts[0].x = -1.0F * flipX;
      verts[0].y = -1.0F * flipY;
      verts[1].x =  1.0F * flipX;
      verts[1].y = -1.0F * flipY;
      verts[2].x =  1.0F * flipX;
      verts[2].y =  1.0F * flipY;
      verts[3].x = -1.0F * flipX;
      verts[3].y =  1.0F * flipY;

      verts[0].tex[0] = s0;
      verts[0].tex[1] = t0;
      verts[0].tex[2] = readAtt->Zoffset;
      verts[1].tex[0] = s1;
      verts[1].tex[1] = t0;
      verts[1].tex[2] = readAtt->Zoffset;
      verts[2].tex[0] = s1;
      verts[2].tex[1] = t1;
      verts[2].tex[2] = readAtt->Zoffset;
      verts[3].tex[0] = s0;
      verts[3].tex[1] = t1;
      verts[3].tex[2] = readAtt->Zoffset;

      _mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts,
                            __func__);
   }

   /* setup viewport */
   _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH);
   _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth);
   _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth);
   _mesa_DepthMask(do_depth);
   _mesa_DepthFunc(GL_ALWAYS);

   _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
   _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit);

   return true;
}
Esempio n. 13
0
static GLboolean
update_single_texture(struct st_context *st,
                      struct pipe_sampler_view **sampler_view,
		      GLuint texUnit)
{
   struct pipe_context *pipe = st->pipe;
   struct gl_context *ctx = st->ctx;
   const struct gl_sampler_object *samp;
   struct gl_texture_object *texObj;
   struct st_texture_object *stObj;
   enum pipe_format st_view_format;
   GLboolean retval;

   samp = _mesa_get_samplerobj(ctx, texUnit);

   texObj = ctx->Texture.Unit[texUnit]._Current;

   if (!texObj) {
      texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
      samp = &texObj->Sampler;
   }
   stObj = st_texture_object(texObj);

   retval = st_finalize_texture(ctx, st->pipe, texObj);
   if (!retval) {
      /* out of mem */
      return GL_FALSE;
   }

   /* Determine the format of the texture sampler view */
   st_view_format = stObj->pt->format;
   {
      const struct st_texture_image *firstImage =
	 st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
      const gl_format texFormat = firstImage->base.TexFormat;
      enum pipe_format firstImageFormat =
	 st_mesa_format_to_pipe_format(texFormat);

      if ((samp->sRGBDecode == GL_SKIP_DECODE_EXT) &&
	  (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) {
         /* Don't do sRGB->RGB conversion.  Interpret the texture data as
          * linear values.
          */
	 const gl_format linearFormat =
	    _mesa_get_srgb_format_linear(texFormat);
	 firstImageFormat = st_mesa_format_to_pipe_format(linearFormat);
      }

      if (firstImageFormat != stObj->pt->format)
	 st_view_format = firstImageFormat;
   }

   /* if sampler view has changed dereference it */
   if (stObj->sampler_view) {
      if (check_sampler_swizzle(stObj->sampler_view,
				stObj->base._Swizzle,
				samp->DepthMode) ||
	  (st_view_format != stObj->sampler_view->format) ||
	  stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) {
	 pipe_sampler_view_reference(&stObj->sampler_view, NULL);
      }
   }

   *sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe,
							  samp,
							  st_view_format);
   return GL_TRUE;
}
Esempio n. 14
0
/**
 * Check if the call to _mesa_meta_GenerateMipmap() will require a
 * software fallback.  The fallback path will require that the texture
 * images are mapped.
 * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
 */
static bool
fallback_required(struct gl_context *ctx, GLenum target,
                  struct gl_texture_object *texObj)
{
   struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
   struct gl_texture_image *baseImage;
   GLuint srcLevel;
   GLenum status;

   /* check for fallbacks */
   if (target == GL_TEXTURE_3D) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() to %s target\n",
                       _mesa_enum_to_string(target));
      return true;
   }

   srcLevel = texObj->BaseLevel;
   baseImage = _mesa_select_tex_image(texObj, target, srcLevel);
   if (!baseImage) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() couldn't find base teximage\n");
      return true;
   }

   if (_mesa_is_format_compressed(baseImage->TexFormat)) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() with %s format\n",
                       _mesa_get_format_name(baseImage->TexFormat));
      return true;
   }

   if (_mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB &&
       !ctx->Extensions.EXT_texture_sRGB_decode) {
      /* The texture format is sRGB but we can't turn off sRGB->linear
       * texture sample conversion.  So we won't be able to generate the
       * right colors when rendering.  Need to use a fallback.
       */
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() of sRGB texture without "
                       "sRGB decode\n");
      return true;
   }

   /*
    * Test that we can actually render in the texture's format.
    */
   if (mipmap->fb == NULL) {
      mipmap->fb = ctx->Driver.NewFramebuffer(ctx, 0xDEADBEEF);
      if (mipmap->fb == NULL) {
         _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                          "glGenerateMipmap() ran out of memory\n");
         return true;
      }
   }

   _mesa_meta_framebuffer_texture_image(ctx, mipmap->fb,
                                        GL_COLOR_ATTACHMENT0, baseImage, 0);

   status = _mesa_check_framebuffer_status(ctx, mipmap->fb);
   if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() got incomplete FBO\n");
      return true;
   }

   return false;
}
Esempio n. 15
0
/**
 * Check if the call to _mesa_meta_GenerateMipmap() will require a
 * software fallback.  The fallback path will require that the texture
 * images are mapped.
 * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise
 */
static bool
fallback_required(struct gl_context *ctx, GLenum target,
                  struct gl_texture_object *texObj)
{
   const GLuint fboSave = ctx->DrawBuffer->Name;
   struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap;
   struct gl_texture_image *baseImage;
   GLuint srcLevel;
   GLenum status;

   /* GL_DRAW_FRAMEBUFFER does not exist in OpenGL ES 1.x, and since
    * _mesa_meta_begin hasn't been called yet, we have to work-around API
    * difficulties.  The whole reason that GL_DRAW_FRAMEBUFFER is used instead
    * of GL_FRAMEBUFFER is that the read framebuffer may be different.  This
    * is moot in OpenGL ES 1.x.
    */
   const GLenum fbo_target = ctx->API == API_OPENGLES
      ? GL_FRAMEBUFFER : GL_DRAW_FRAMEBUFFER;

   /* check for fallbacks */
   if (target == GL_TEXTURE_3D) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() to %s target\n",
                       _mesa_enum_to_string(target));
      return true;
   }

   srcLevel = texObj->BaseLevel;
   baseImage = _mesa_select_tex_image(texObj, target, srcLevel);
   if (!baseImage) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() couldn't find base teximage\n");
      return true;
   }

   if (_mesa_is_format_compressed(baseImage->TexFormat)) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() with %s format\n",
                       _mesa_get_format_name(baseImage->TexFormat));
      return true;
   }

   if (_mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB &&
       !ctx->Extensions.EXT_texture_sRGB_decode) {
      /* The texture format is sRGB but we can't turn off sRGB->linear
       * texture sample conversion.  So we won't be able to generate the
       * right colors when rendering.  Need to use a fallback.
       */
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() of sRGB texture without "
                       "sRGB decode\n");
      return true;
   }

   /*
    * Test that we can actually render in the texture's format.
    */
   if (!mipmap->FBO)
      _mesa_GenFramebuffers(1, &mipmap->FBO);
   _mesa_BindFramebuffer(fbo_target, mipmap->FBO);

   _mesa_meta_bind_fbo_image(fbo_target, GL_COLOR_ATTACHMENT0, baseImage, 0);

   status = _mesa_CheckFramebufferStatus(fbo_target);

   _mesa_BindFramebuffer(fbo_target, fboSave);

   if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_HIGH,
                       "glGenerateMipmap() got incomplete FBO\n");
      return true;
   }

   return false;
}
Esempio n. 16
0
/**
 * The glGet queries of the framebuffer red/green/blue size, stencil size,
 * etc. are satisfied by the fields of ctx->DrawBuffer->Visual.  These can
 * change depending on the renderbuffer bindings.  This function updates
 * the given framebuffer's Visual from the current renderbuffer bindings.
 *
 * This may apply to user-created framebuffers or window system framebuffers.
 *
 * Also note: ctx->DrawBuffer->Visual.depthBits might not equal
 * ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer.DepthBits.
 * The former one is used to convert floating point depth values into
 * integer Z values.
 */
void
_mesa_update_framebuffer_visual(struct gl_context *ctx,
				struct gl_framebuffer *fb)
{
   GLuint i;

   memset(&fb->Visual, 0, sizeof(fb->Visual));
   fb->Visual.rgbMode = GL_TRUE; /* assume this */

#if 0 /* this _might_ be needed */
   if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      /* leave visual fields zero'd */
      return;
   }
#endif

   /* find first RGB renderbuffer */
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const GLenum baseFormat = _mesa_get_format_base_format(rb->Format);
         const gl_format fmt = rb->Format;

         if (_mesa_is_legal_color_format(ctx, baseFormat)) {
            fb->Visual.redBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
            fb->Visual.greenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
            fb->Visual.blueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
            fb->Visual.alphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
            fb->Visual.rgbBits = fb->Visual.redBits
               + fb->Visual.greenBits + fb->Visual.blueBits;
            fb->Visual.samples = rb->NumSamples;
            fb->Visual.sampleBuffers = rb->NumSamples > 0 ? 1 : 0;
            if (_mesa_get_format_color_encoding(fmt) == GL_SRGB)
                fb->Visual.sRGBCapable = ctx->Const.sRGBCapable;
            break;
         }
      }
   }

   fb->Visual.floatMode = GL_FALSE;
   for (i = 0; i < BUFFER_COUNT; i++) {
      if (fb->Attachment[i].Renderbuffer) {
         const struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer;
         const gl_format fmt = rb->Format;

         if (_mesa_get_format_datatype(fmt) == GL_FLOAT) {
            fb->Visual.floatMode = GL_TRUE;
            break;
         }
      }
   }

   if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_DEPTH].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveDepthBuffer = GL_TRUE;
      fb->Visual.depthBits = _mesa_get_format_bits(fmt, GL_DEPTH_BITS);
   }

   if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_STENCIL].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveStencilBuffer = GL_TRUE;
      fb->Visual.stencilBits = _mesa_get_format_bits(fmt, GL_STENCIL_BITS);
   }

   if (fb->Attachment[BUFFER_ACCUM].Renderbuffer) {
      const struct gl_renderbuffer *rb =
         fb->Attachment[BUFFER_ACCUM].Renderbuffer;
      const gl_format fmt = rb->Format;
      fb->Visual.haveAccumBuffer = GL_TRUE;
      fb->Visual.accumRedBits = _mesa_get_format_bits(fmt, GL_RED_BITS);
      fb->Visual.accumGreenBits = _mesa_get_format_bits(fmt, GL_GREEN_BITS);
      fb->Visual.accumBlueBits = _mesa_get_format_bits(fmt, GL_BLUE_BITS);
      fb->Visual.accumAlphaBits = _mesa_get_format_bits(fmt, GL_ALPHA_BITS);
   }

   compute_depth_max(fb);
}
Esempio n. 17
0
/**
 * This is the software fallback for Driver.GetTexImage().
 * All error checking will have been done before this routine is called.
 * The texture image must be mapped.
 */
void
_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
                   GLenum format, GLenum type, GLvoid *pixels,
                   struct gl_texture_object *texObj,
                   struct gl_texture_image *texImage)
{
   GLuint dimensions;

   /* If we get here, the texture image should be mapped */
   assert(texImage->Data);

   switch (target) {
   case GL_TEXTURE_1D:
      dimensions = 1;
      break;
   case GL_TEXTURE_3D:
      dimensions = 3;
      break;
   default:
      dimensions = 2;
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      /* Packing texture image into a PBO.
       * Map the (potentially) VRAM-based buffer into our process space so
       * we can write into it with the code below.
       * A hardware driver might use a sophisticated blit to move the
       * texture data to the PBO if the PBO is in VRAM along with the texture.
       */
      GLubyte *buf = (GLubyte *)
         ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                               GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
      if (!buf) {
         /* out of memory or other unexpected error */
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
         return;
      }
      /* <pixels> was an offset into the PBO.
       * Now make it a real, client-side pointer inside the mapped region.
       */
      pixels = ADD_POINTERS(buf, pixels);
   }

   if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) {
      /* all done */
   }
   else if (format == GL_COLOR_INDEX) {
      get_tex_color_index(ctx, dimensions, format, type, pixels, texImage);
   }
   else if (format == GL_DEPTH_COMPONENT) {
      get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
   }
   else if (format == GL_DEPTH_STENCIL_EXT) {
      get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage);
   }
   else if (format == GL_YCBCR_MESA) {
      get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
   }
   else if (_mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB) {
      get_tex_srgb(ctx, dimensions, format, type, pixels, texImage);
   }
   else {
      get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
   }

   if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
                              ctx->Pack.BufferObj);
   }
}