Exemplo n.º 1
0
/**
 * Update the renderbuffer wrapper for rendering to a texture.
 * For example, update the width, height of the RB based on the texture size,
 * update the internal format info, etc.
 */
static void
update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
{
   struct gl_renderbuffer *rb = att->Renderbuffer;
   struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
   struct swrast_texture_image *swImage;
   gl_format format;
   GLuint zOffset;

   (void) ctx;

   swImage = swrast_texture_image(_mesa_get_attachment_teximage(att));
   assert(swImage);

   format = swImage->Base.TexFormat;

   if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
      zOffset = 0;
   }
   else {
      zOffset = att->Zoffset;
   }

   rb->Width = swImage->Base.Width;
   rb->Height = swImage->Base.Height;
   rb->InternalFormat = swImage->Base.InternalFormat;
   rb->_BaseFormat = _mesa_get_format_base_format(format);

   /* Want to store linear values, not sRGB */
   rb->Format = _mesa_get_srgb_format_linear(format);
 
   /* Set the gl_renderbuffer::Buffer field so that mapping the buffer
    * succeeds.
     */
   if (att->Texture->Target == GL_TEXTURE_3D ||
       att->Texture->Target == GL_TEXTURE_2D_ARRAY_EXT) {
      srb->Buffer = swImage->Buffer +
         swImage->ImageOffsets[zOffset] * _mesa_get_format_bytes(format);
   }
   else {
      srb->Buffer = swImage->Buffer;
   }
}
/**
 * Called by glFramebufferTexture[123]DEXT() (and other places) to
 * prepare for rendering into texture memory.  This might be called
 * many times to choose different texture levels, cube faces, etc
 * before intel_finish_render_texture() is ever called.
 */
static void
intel_render_texture(struct gl_context * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
   struct intel_texture_image *intel_image = intel_texture_image(image);
   struct intel_mipmap_tree *mt = intel_image->mt;
   int layer;

   (void) fb;

   if (att->CubeMapFace > 0) {
      assert(att->Zoffset == 0);
      layer = att->CubeMapFace;
   } else {
      layer = att->Zoffset;
   }

   if (!intel_image->mt) {
      /* Fallback on drawing to a texture that doesn't have a miptree
       * (has a border, width/height 0, etc.)
       */
      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
      _swrast_render_texture(ctx, fb, att);
      return;
   }
   else if (!irb) {
      intel_miptree_check_level_layer(mt, att->TextureLevel, layer);

      irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0);

      if (irb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base);
      }
      else {
         /* fallback to software rendering */
         _swrast_render_texture(ctx, fb, att);
         return;
      }
   }

   if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _swrast_render_texture(ctx, fb, att);
       return;
   }

   irb->tex_image = image;

   DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
       _mesa_get_format_name(image->TexFormat),
       att->Texture->Name, image->Width, image->Height,
       irb->Base.Base.RefCount);

   /* update drawing region, etc */
   intel_draw_buffer(ctx);
}
/**
 * Called by ctx->Driver.RenderTexture
 */
static void
st_render_texture(struct gl_context *ctx,
                  struct gl_framebuffer *fb,
                  struct gl_renderbuffer_attachment *att)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct st_renderbuffer *strb;
   struct gl_renderbuffer *rb;
   struct pipe_resource *pt;
   struct st_texture_object *stObj;
   const struct gl_texture_image *texImage;
   struct pipe_surface surf_tmpl;

   if (!st_finalize_texture(ctx, pipe, att->Texture))
      return;

   pt = st_get_texobj_resource(att->Texture);
   assert(pt);

   /* get pointer to texture image we're rendeing to */
   texImage = _mesa_get_attachment_teximage(att);

   /* create new renderbuffer which wraps the texture image.
    * Use the texture's name as the renderbuffer's name so that we have
    * something that's non-zero (to determine vertical orientation) and
    * possibly helpful for debugging.
    */
   rb = st_new_renderbuffer(ctx, att->Texture->Name);
   if (!rb) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
      return;
   }

   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
   assert(rb->RefCount == 1);
   rb->AllocStorage = NULL; /* should not get called */
   strb = st_renderbuffer(rb);

   assert(strb->Base.RefCount > 0);

   /* get the texture for the texture object */
   stObj = st_texture_object(att->Texture);

   /* point renderbuffer at texobject */
   strb->rtt = stObj;
   strb->rtt_level = att->TextureLevel;
   strb->rtt_face = att->CubeMapFace;
   strb->rtt_slice = att->Zoffset;

   rb->Width = texImage->Width2;
   rb->Height = texImage->Height2;
   rb->_BaseFormat = texImage->_BaseFormat;
   rb->InternalFormat = texImage->InternalFormat;

   pipe_resource_reference( &strb->texture, pt );

   pipe_surface_release(pipe, &strb->surface);

   assert(strb->rtt_level <= strb->texture->last_level);

   /* new surface for rendering into the texture */
   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = ctx->Color.sRGBEnabled
      ? strb->texture->format : util_format_linear(strb->texture->format);
   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
   surf_tmpl.u.tex.level = strb->rtt_level;
   surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
   surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
   strb->surface = pipe->create_surface(pipe,
                                        strb->texture,
                                        &surf_tmpl);

   strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);

   /* Invalidate buffer state so that the pipe's framebuffer state
    * gets updated.
    * That's where the new renderbuffer (which we just created) gets
    * passed to the pipe as a (color/depth) render target.
    */
   st_invalidate_state(ctx, _NEW_BUFFERS);


   /* Need to trigger a call to update_framebuffer() since we just
    * attached a new renderbuffer.
    */
   ctx->NewState |= _NEW_BUFFERS;
}
Exemplo n.º 4
0
/**
 * Called by ctx->Driver.RenderTexture
 */
static void
st_render_texture(struct gl_context *ctx,
                  struct gl_framebuffer *fb,
                  struct gl_renderbuffer_attachment *att)
{
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct gl_renderbuffer *rb = att->Renderbuffer;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct pipe_resource *pt;
   struct st_texture_object *stObj;
   const struct gl_texture_image *texImage;
   struct pipe_surface surf_tmpl;

   if (!st_finalize_texture(ctx, pipe, att->Texture))
      return;

   pt = st_get_texobj_resource(att->Texture);
   assert(pt);

   /* get pointer to texture image we're rendeing to */
   texImage = _mesa_get_attachment_teximage(att);

   /* get the texture for the texture object */
   stObj = st_texture_object(att->Texture);

   /* point renderbuffer at texobject */
   strb->rtt = stObj;
   strb->rtt_level = att->TextureLevel;
   strb->rtt_face = att->CubeMapFace;
   strb->rtt_slice = att->Zoffset;

   pipe_resource_reference( &strb->texture, pt );

   pipe_surface_release(pipe, &strb->surface);

   assert(strb->rtt_level <= strb->texture->last_level);

   /* new surface for rendering into the texture */
   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = ctx->Color.sRGBEnabled
      ? strb->texture->format : util_format_linear(strb->texture->format);
   surf_tmpl.u.tex.level = strb->rtt_level;
   surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
   surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
   strb->surface = pipe->create_surface(pipe,
                                        strb->texture,
                                        &surf_tmpl);

   strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);

   /* Invalidate buffer state so that the pipe's framebuffer state
    * gets updated.
    * That's where the new renderbuffer (which we just created) gets
    * passed to the pipe as a (color/depth) render target.
    */
   st_invalidate_state(ctx, _NEW_BUFFERS);


   /* Need to trigger a call to update_framebuffer() since we just
    * attached a new renderbuffer.
    */
   ctx->NewState |= _NEW_BUFFERS;
}
Exemplo n.º 5
0
/**
 * Called by glFramebufferTexture[123]DEXT() (and other places) to
 * prepare for rendering into texture memory.  This might be called
 * many times to choose different texture levels, cube faces, etc
 * before intel_finish_render_texture() is ever called.
 */
static void
intel_render_texture(struct gl_context * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
    struct intel_context *intel = intel_context(ctx);
    struct gl_texture_image *image = _mesa_get_attachment_teximage(att);
    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
    struct intel_texture_image *intel_image = intel_texture_image(image);
    struct intel_mipmap_tree *mt = intel_image->mt;
    int layer;

    (void) fb;

    if (att->CubeMapFace > 0) {
        assert(att->Zoffset == 0);
        layer = att->CubeMapFace;
    } else {
        layer = att->Zoffset;
    }

    if (!intel_image->mt) {
        /* Fallback on drawing to a texture that doesn't have a miptree
         * (has a border, width/height 0, etc.)
         */
        _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
        _swrast_render_texture(ctx, fb, att);
        return;
    }
    else if (!irb) {
        intel_miptree_check_level_layer(mt, att->TextureLevel, layer);

        irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0);

        if (irb) {
            /* bind the wrapper to the attachment point */
            _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base);
        }
        else {
            /* fallback to software rendering */
            _swrast_render_texture(ctx, fb, att);
            return;
        }
    }

    if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) {
        _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
        _swrast_render_texture(ctx, fb, att);
        return;
    }

    DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n",
        _mesa_get_format_name(image->TexFormat),
        att->Texture->Name, image->Width, image->Height,
        irb->Base.Base.RefCount);

    intel_image->used_as_render_target = true;

#ifndef I915
    if (need_tile_offset_workaround(brw_context(ctx), irb)) {
        /* Original gen4 hardware couldn't draw to a non-tile-aligned
         * destination in a miptree unless you actually setup your
         * renderbuffer as a miptree and used the fragile
         * lod/array_index/etc. controls to select the image.  So,
         * instead, we just make a new single-level miptree and render
         * into that.
         */
        struct intel_context *intel = intel_context(ctx);
        struct intel_mipmap_tree *new_mt;
        int width, height, depth;

        intel_miptree_get_dimensions_for_image(image, &width, &height, &depth);

        new_mt = intel_miptree_create(intel, image->TexObject->Target,
                                      intel_image->base.Base.TexFormat,
                                      intel_image->base.Base.Level,
                                      intel_image->base.Base.Level,
                                      width, height, depth,
                                      true);

        intel_miptree_copy_teximage(intel, intel_image, new_mt);
        intel_renderbuffer_set_draw_offset(irb);

        intel_miptree_reference(&irb->mt, intel_image->mt);
        intel_miptree_release(&new_mt);
    }
#endif
    /* update drawing region, etc */
    intel_draw_buffer(ctx);
}