예제 #1
0
/**
 * Update the framebuffer's _DepthBuffer field using the renderbuffer
 * found at the given attachment index.
 *
 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
 * create and install a depth wrapper/adaptor.
 *
 * \param fb  the framebuffer whose _DepthBuffer field to update
 * \param attIndex  indicates the renderbuffer to possibly wrap
 */
void
_mesa_update_depth_buffer(struct gl_context *ctx,
                          struct gl_framebuffer *fb,
                          GLuint attIndex)
{
   struct gl_renderbuffer *depthRb;

   /* only one possiblity for now */
   ASSERT(attIndex == BUFFER_DEPTH);

   depthRb = fb->Attachment[attIndex].Renderbuffer;

   if (depthRb && _mesa_is_format_packed_depth_stencil(depthRb->Format)) {
      /* The attached depth buffer is a GL_DEPTH_STENCIL renderbuffer */
      if (!fb->_DepthBuffer
          || fb->_DepthBuffer->Wrapped != depthRb
          || _mesa_get_format_base_format(fb->_DepthBuffer->Format) != GL_DEPTH_COMPONENT) {
         /* need to update wrapper */
         struct gl_renderbuffer *wrapper
            = _mesa_new_z24_renderbuffer_wrapper(ctx, depthRb);
         _mesa_reference_renderbuffer(&fb->_DepthBuffer, wrapper);
         ASSERT(fb->_DepthBuffer->Wrapped == depthRb);
      }
   }
   else {
      /* depthRb may be null */
      _mesa_reference_renderbuffer(&fb->_DepthBuffer, depthRb);
   }
}
예제 #2
0
/**
 * Free all the data hanging off the given gl_framebuffer, but don't free
 * the gl_framebuffer object itself.
 */
void
_mesa_free_framebuffer_data(struct gl_framebuffer *fb)
{
   GLuint i;

   assert(fb);
   assert(fb->RefCount == 0);

   _glthread_DESTROY_MUTEX(fb->Mutex);

   for (i = 0; i < BUFFER_COUNT; i++) {
      struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
      if (att->Renderbuffer) {
         _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
      }
      if (att->Texture) {
         _mesa_reference_texobj(&att->Texture, NULL);
      }
      ASSERT(!att->Renderbuffer);
      ASSERT(!att->Texture);
      att->Type = GL_NONE;
   }

   /* unbind _Depth/_StencilBuffer to decr ref counts */
   _mesa_reference_renderbuffer(&fb->_DepthBuffer, NULL);
   _mesa_reference_renderbuffer(&fb->_StencilBuffer, NULL);
}
예제 #3
0
/**
 * Update the framebuffer's _StencilBuffer field using the renderbuffer
 * found at the given attachment index.
 *
 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
 * create and install a stencil wrapper/adaptor.
 *
 * \param fb  the framebuffer whose _StencilBuffer field to update
 * \param attIndex  indicates the renderbuffer to possibly wrap
 */
void
_mesa_update_stencil_buffer(struct gl_context *ctx,
                            struct gl_framebuffer *fb,
                            GLuint attIndex)
{
   struct gl_renderbuffer *stencilRb;

   ASSERT(attIndex == BUFFER_DEPTH ||
          attIndex == BUFFER_STENCIL);

   stencilRb = fb->Attachment[attIndex].Renderbuffer;

   if (stencilRb && _mesa_is_format_packed_depth_stencil(stencilRb->Format)) {
      /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
      if (!fb->_StencilBuffer
          || fb->_StencilBuffer->Wrapped != stencilRb
          || _mesa_get_format_base_format(fb->_StencilBuffer->Format) != GL_STENCIL_INDEX) {
         /* need to update wrapper */
         struct gl_renderbuffer *wrapper
            = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
         _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
         ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
      }
   }
   else {
      /* stencilRb may be null */
      _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
   }
}
예제 #4
0
파일: intel_tex.c 프로젝트: nikai3d/mesa
static void
intelFreeTextureImageData(struct gl_context * ctx, struct gl_texture_image *texImage)
{
   struct intel_context *intel = intel_context(ctx);
   struct intel_texture_image *intelImage = intel_texture_image(texImage);

   DBG("%s\n", __FUNCTION__);

   if (intelImage->mt) {
      intel_miptree_release(intel, &intelImage->mt);
   }

   if (texImage->Data) {
      _mesa_free_texmemory(texImage->Data);
      texImage->Data = NULL;
   }

   if (intelImage->depth_rb) {
      _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL);
   }

   if (intelImage->stencil_rb) {
      _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL);
   }
}
예제 #5
0
/**
 * Update the framebuffer's _StencilBuffer field using the renderbuffer
 * found at the given attachment index.
 *
 * If that attachment points to a combined GL_DEPTH_STENCIL renderbuffer,
 * create and install a stencil wrapper/adaptor.
 *
 * \param fb  the framebuffer whose _StencilBuffer field to update
 * \param attIndex  indicates the renderbuffer to possibly wrap
 */
void
_mesa_update_stencil_buffer(GLcontext *ctx,
                            struct gl_framebuffer *fb,
                            GLuint attIndex)
{
   struct gl_renderbuffer *stencilRb;

   ASSERT(attIndex == BUFFER_DEPTH ||
          attIndex == BUFFER_STENCIL);

   stencilRb = fb->Attachment[attIndex].Renderbuffer;

   if (stencilRb && stencilRb->_ActualFormat == GL_DEPTH24_STENCIL8_EXT) {
      /* The attached stencil buffer is a GL_DEPTH_STENCIL renderbuffer */
      if (!fb->_StencilBuffer
          || fb->_StencilBuffer->Wrapped != stencilRb
          || fb->_StencilBuffer->_BaseFormat != GL_STENCIL_INDEX) {
         /* need to update wrapper */
         struct gl_renderbuffer *wrapper
            = _mesa_new_s8_renderbuffer_wrapper(ctx, stencilRb);
         _mesa_reference_renderbuffer(&fb->_StencilBuffer, wrapper);
         ASSERT(fb->_StencilBuffer->Wrapped == stencilRb);
      }
   }
   else {
      /* stencilRb may be null */
      _mesa_reference_renderbuffer(&fb->_StencilBuffer, stencilRb);
   }
}
예제 #6
0
static void
nouveau_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb,
		       struct gl_renderbuffer_attachment *att)
{
	struct gl_renderbuffer *rb = att->Renderbuffer;
	struct gl_texture_image *ti =
		att->Texture->Image[att->CubeMapFace][att->TextureLevel];

	/* Allocate a renderbuffer object for the texture if we
	 * haven't already done so. */
	if (!rb) {
		rb = nouveau_renderbuffer_new(ctx, ~0);
		assert(rb);

		rb->AllocStorage = NULL;
		_mesa_reference_renderbuffer(&att->Renderbuffer, rb);
	}

	/* Update the renderbuffer fields from the texture. */
	set_renderbuffer_format(rb, get_tex_format(ti));
	rb->Width = ti->Width;
	rb->Height = ti->Height;
	nouveau_surface_ref(&to_nouveau_teximage(ti)->surface,
			    &to_nouveau_renderbuffer(rb)->surface);

	context_dirty(ctx, FRAMEBUFFER);
}
예제 #7
0
/**
 * Attach a renderbuffer to a framebuffer.
 * \param bufferName  one of the BUFFER_x tokens
 */
void
_mesa_add_renderbuffer(struct gl_framebuffer *fb,
                       gl_buffer_index bufferName, struct gl_renderbuffer *rb)
{
   assert(fb);
   assert(rb);
   assert(bufferName < BUFFER_COUNT);

   /* There should be no previous renderbuffer on this attachment point,
    * with the exception of depth/stencil since the same renderbuffer may
    * be used for both.
    */
   assert(bufferName == BUFFER_DEPTH ||
          bufferName == BUFFER_STENCIL ||
          fb->Attachment[bufferName].Renderbuffer == NULL);

   /* winsys vs. user-created buffer cross check */
   if (fb->Name) {
      assert(rb->Name);
   }
   else {
      assert(!rb->Name);
   }

   fb->Attachment[bufferName].Type = GL_RENDERBUFFER_EXT;
   fb->Attachment[bufferName].Complete = GL_TRUE;
   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer, rb);
}
예제 #8
0
파일: fbobject.c 프로젝트: mariuz/haiku
void GLAPIENTRY
_mesa_DeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
{
   GLint i;
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END(ctx);
   FLUSH_VERTICES(ctx, _NEW_BUFFERS);

   for (i = 0; i < n; i++) {
      if (renderbuffers[i] > 0) {
	 struct gl_renderbuffer *rb;
	 rb = _mesa_lookup_renderbuffer(ctx, renderbuffers[i]);
	 if (rb) {
            /* check if deleting currently bound renderbuffer object */
            if (rb == ctx->CurrentRenderbuffer) {
               /* bind default */
               ASSERT(rb->RefCount >= 2);
               _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
            }

	    /* Remove from hash table immediately, to free the ID.
             * But the object will not be freed until it's no longer
             * referenced anywhere else.
             */
	    _mesa_HashRemove(ctx->Shared->RenderBuffers, renderbuffers[i]);

            if (rb != &DummyRenderbuffer) {
               /* no longer referenced by hash table */
               _mesa_reference_renderbuffer(&rb, NULL);
	    }
	 }
      }
   }
}
예제 #9
0
/**
 * Remove the named renderbuffer from the given framebuffer.
 * \param bufferName  one of the BUFFER_x tokens
 */
void
_mesa_remove_renderbuffer(struct gl_framebuffer *fb,
                          gl_buffer_index bufferName)
{
   assert(bufferName < BUFFER_COUNT);
   _mesa_reference_renderbuffer(&fb->Attachment[bufferName].Renderbuffer,
                                NULL);
}
예제 #10
0
/**
 * Delete a depth or stencil wrapper renderbuffer.
 */
static void
delete_wrapper(struct gl_renderbuffer *rb)
{
   ASSERT(rb->Format == MESA_FORMAT_S8 ||
          rb->Format == MESA_FORMAT_X8_Z24);
   _mesa_reference_renderbuffer(&rb->Wrapped, NULL);
   free(rb);
}
void
brw_meta_resolve_color(struct brw_context *brw,
                       struct intel_mipmap_tree *mt)
{
    struct gl_context *ctx = &brw->ctx;
    GLuint fbo;
    struct gl_renderbuffer *rb;
    struct rect rect;

    brw_emit_mi_flush(brw);

    _mesa_meta_begin(ctx, MESA_META_ALL);

    _mesa_GenFramebuffers(1, &fbo);
    rb = brw_get_rb_for_slice(brw, mt, 0, 0, false);

    _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    _mesa_framebuffer_renderbuffer(ctx, ctx->DrawBuffer, GL_COLOR_ATTACHMENT0,
                                   rb);
    _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0);

    brw_fast_clear_init(brw);

    use_rectlist(brw, true);

    brw_bind_rep_write_shader(brw, (float *) fast_clear_color);

    /* SKL+ also has a resolve mode for compressed render targets and thus more
     * bits to let us select the type of resolve.  For fast clear resolves, it
     * turns out we can use the same value as pre-SKL though.
     */
    if (intel_miptree_is_lossless_compressed(brw, mt))
        set_fast_clear_op(brw, GEN9_PS_RENDER_TARGET_RESOLVE_FULL);
    else
        set_fast_clear_op(brw, GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE);

    mt->fast_clear_state = INTEL_FAST_CLEAR_STATE_RESOLVED;
    get_resolve_rect(brw, mt, &rect);

    brw_draw_rectlist(brw, &rect, 1);

    set_fast_clear_op(brw, 0);
    use_rectlist(brw, false);

    _mesa_reference_renderbuffer(&rb, NULL);
    _mesa_DeleteFramebuffers(1, &fbo);

    _mesa_meta_end(ctx);

    /* We're typically called from intel_update_state() and we're supposed to
     * return with the state all updated to what it was before
     * brw_meta_resolve_color() was called.  The meta rendering will have
     * messed up the state and we need to call _mesa_update_state() again to
     * get back to where we were supposed to be when resolve was called.
     */
    if (ctx->NewState)
        _mesa_update_state(ctx);
}
예제 #12
0
파일: fbobject.c 프로젝트: mariuz/haiku
/**
 * Bind a renderbuffer to an attachment point.
 * The previous binding, if any, will be removed first.
 */
void
_mesa_set_renderbuffer_attachment(GLcontext *ctx,
                                  struct gl_renderbuffer_attachment *att,
                                  struct gl_renderbuffer *rb)
{
   /* XXX check if re-doing same attachment, exit early */
   _mesa_remove_attachment(ctx, att);
   att->Type = GL_RENDERBUFFER_EXT;
   att->Texture = NULL; /* just to be safe */
   att->Complete = GL_FALSE;
   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
}
예제 #13
0
void
intel_flip_renderbuffers(struct intel_framebuffer *intel_fb)
{
   int current_page = intel_fb->pf_current_page;
   int next_page = (current_page + 1) % intel_fb->pf_num_pages;
   struct gl_renderbuffer *tmp_rb;

   /* Exchange renderbuffers if necessary but make sure their reference counts
    * are preserved.
    */
   if (intel_fb->color_rb[current_page] &&
       intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer !=
       &intel_fb->color_rb[current_page]->Base) {
      tmp_rb = NULL;
      _mesa_reference_renderbuffer(&tmp_rb,
	 intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
      tmp_rb = &intel_fb->color_rb[current_page]->Base;
      _mesa_reference_renderbuffer(
	 &intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer, tmp_rb);
      _mesa_reference_renderbuffer(&tmp_rb, NULL);
   }

   if (intel_fb->color_rb[next_page] &&
       intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer !=
       &intel_fb->color_rb[next_page]->Base) {
      tmp_rb = NULL;
      _mesa_reference_renderbuffer(&tmp_rb,
	 intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
      tmp_rb = &intel_fb->color_rb[next_page]->Base;
      _mesa_reference_renderbuffer(
	 &intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer, tmp_rb);
      _mesa_reference_renderbuffer(&tmp_rb, NULL);
   }
}
예제 #14
0
파일: fbobject.c 프로젝트: mariuz/haiku
void GLAPIENTRY
_mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer)
{
   struct gl_renderbuffer *newRb;
   GET_CURRENT_CONTEXT(ctx);

   ASSERT_OUTSIDE_BEGIN_END(ctx);

   if (target != GL_RENDERBUFFER_EXT) {
         _mesa_error(ctx, GL_INVALID_ENUM,
                  "glBindRenderbufferEXT(target)");
      return;
   }

   FLUSH_VERTICES(ctx, _NEW_BUFFERS);
   /* The above doesn't fully flush the drivers in the way that a
    * glFlush does, but that is required here:
    */
   if (ctx->Driver.Flush)
      ctx->Driver.Flush(ctx);


   if (renderbuffer) {
      newRb = _mesa_lookup_renderbuffer(ctx, renderbuffer);
      if (newRb == &DummyRenderbuffer) {
         /* ID was reserved, but no real renderbuffer object made yet */
         newRb = NULL;
      }
      if (!newRb) {
	 /* create new renderbuffer object */
	 newRb = ctx->Driver.NewRenderbuffer(ctx, renderbuffer);
	 if (!newRb) {
	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindRenderbufferEXT");
	    return;
	 }
         ASSERT(newRb->AllocStorage);
         _mesa_HashInsert(ctx->Shared->RenderBuffers, renderbuffer, newRb);
         newRb->RefCount = 1; /* referenced by hash table */
      }
   }
   else {
      newRb = NULL;
   }

   ASSERT(newRb != &DummyRenderbuffer);

   _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb);
}
예제 #15
0
/**
 * Destroy an Off-Screen Mesa rendering context.
 *
 * \param osmesa  the context to destroy
 */
GLAPI void GLAPIENTRY
OSMesaDestroyContext( OSMesaContext osmesa )
{
   if (osmesa) {
      if (osmesa->rb)
         _mesa_reference_renderbuffer(&osmesa->rb, NULL);

      _swsetup_DestroyContext( &osmesa->mesa );
      _tnl_DestroyContext( &osmesa->mesa );
      _vbo_DestroyContext( &osmesa->mesa );
      _swrast_DestroyContext( &osmesa->mesa );

      _mesa_destroy_visual( osmesa->gl_visual );
      _mesa_unreference_framebuffer( &osmesa->gl_buffer );

      _mesa_free_context_data( &osmesa->mesa );
      _mesa_free( osmesa );
   }
}
예제 #16
0
파일: fbobject.c 프로젝트: mariuz/haiku
/**
 * Remove any texture or renderbuffer attached to the given attachment
 * point.  Update reference counts, etc.
 */
void
_mesa_remove_attachment(GLcontext *ctx, struct gl_renderbuffer_attachment *att)
{
   if (att->Type == GL_TEXTURE) {
      ASSERT(att->Texture);
      if (ctx->Driver.FinishRenderTexture) {
         /* tell driver we're done rendering to this texobj */
         ctx->Driver.FinishRenderTexture(ctx, att);
      }
      _mesa_reference_texobj(&att->Texture, NULL); /* unbind */
      ASSERT(!att->Texture);
   }
   if (att->Type == GL_TEXTURE || att->Type == GL_RENDERBUFFER_EXT) {
      ASSERT(!att->Texture);
      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* unbind */
      ASSERT(!att->Renderbuffer);
   }
   att->Type = GL_NONE;
   att->Complete = GL_TRUE;
}
/**
 * Free all the data hanging off the given gl_framebuffer, but don't free
 * the gl_framebuffer object itself.
 */
void
_mesa_free_framebuffer_data(struct gl_framebuffer *fb)
{
   GLuint i;

   assert(fb);
   assert(fb->RefCount == 0);

   mtx_destroy(&fb->Mutex);

   for (i = 0; i < BUFFER_COUNT; i++) {
      struct gl_renderbuffer_attachment *att = &fb->Attachment[i];
      if (att->Renderbuffer) {
         _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
      }
      if (att->Texture) {
         _mesa_reference_texobj(&att->Texture, NULL);
      }
      assert(!att->Renderbuffer);
      assert(!att->Texture);
      att->Type = GL_NONE;
   }
}
예제 #18
0
/**
 * This function creates a renderbuffer object which wraps a texture image.
 * The new renderbuffer is plugged into the given attachment point.
 * This allows rendering into the texture as if it were a renderbuffer.
 */
static void
wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
{
   struct gl_renderbuffer *rb;
   const GLuint name = 0;

   ASSERT(att->Type == GL_TEXTURE);
   ASSERT(att->Renderbuffer == NULL);

   rb = ctx->Driver.NewRenderbuffer(ctx, name);
   if (!rb) {
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
      return;
   }

   /* init base gl_renderbuffer fields */
   _mesa_init_renderbuffer(rb, name);
   /* plug in our texture_renderbuffer-specific functions */
   rb->Delete = delete_texture_wrapper;
   rb->AllocStorage = NULL; /* illegal! */

   /* update attachment point */
   _mesa_reference_renderbuffer(&att->Renderbuffer, rb);
}
예제 #19
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);
}
/**
 * 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;
}
예제 #22
0
static void
radeon_render_texture(struct gl_context * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct gl_texture_image *newImage
      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
   struct radeon_renderbuffer *rrb = radeon_renderbuffer(att->Renderbuffer);
   radeon_texture_image *radeon_image;
   GLuint imageOffset;

  radeon_print(RADEON_TEXTURE, RADEON_TRACE,
		"%s(%p, fb %p, rrb %p, att %p)\n",
		__func__, ctx, fb, rrb, att);

   (void) fb;

   ASSERT(newImage);

   radeon_image = (radeon_texture_image *)newImage;

   if (!radeon_image->mt || newImage->Border != 0) {
      /* Fallback on drawing to a texture without a miptree.
       */
      _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
      _mesa_render_texture(ctx, fb, att);
      return;
   }
   else if (!rrb) {
      rrb = radeon_wrap_texture(ctx, newImage);
      if (rrb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &rrb->base);
      }
      else {
         /* fallback to software rendering */
         _mesa_render_texture(ctx, fb, att);
         return;
      }
   }

   if (!radeon_update_wrapper(ctx, rrb, newImage)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _mesa_render_texture(ctx, fb, att);
       return;
   }

   DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n",
       _glthread_GetID(),
       att->Texture->Name, newImage->Width, newImage->Height,
       rrb->base.RefCount);

   /* point the renderbufer's region to the texture image region */
   if (rrb->bo != radeon_image->mt->bo) {
      if (rrb->bo)
  	radeon_bo_unref(rrb->bo);
      rrb->bo = radeon_image->mt->bo;
      radeon_bo_ref(rrb->bo);
   }

   /* compute offset of the particular 2D image within the texture region */
   imageOffset = radeon_miptree_image_offset(radeon_image->mt,
                                            att->CubeMapFace,
                                            att->TextureLevel);

   if (att->Texture->Target == GL_TEXTURE_3D) {
      imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride *
                     radeon_image->mt->levels[att->TextureLevel].height *
                     att->Zoffset;
   }

   /* store that offset in the region, along with the correct pitch for
    * the image we are rendering to */
   rrb->draw_offset = imageOffset;
   rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride;

   /* update drawing region, etc */
   radeon_draw_buffer(ctx, fb);
}
예제 #23
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(GLcontext * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct gl_texture_image *newImage
      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
   struct intel_texture_image *intel_image;
   GLuint imageOffset;

   (void) fb;

   ASSERT(newImage);

   if (!irb) {
      irb = intel_wrap_texture(ctx, newImage);
      if (irb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
      }
      else {
         /* fallback to software rendering */
         _mesa_render_texture(ctx, fb, att);
         return;
      }
   } if (!intel_update_wrapper(ctx, irb, newImage)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _mesa_render_texture(ctx, fb, att);
       return;
   }

   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
       _glthread_GetID(),
       att->Texture->Name, newImage->Width, newImage->Height,
       irb->Base.RefCount);

   /* point the renderbufer's region to the texture image region */
   intel_image = intel_texture_image(newImage);
   if (irb->region != intel_image->mt->region) {
      if (irb->region)
	 intel_region_release(&irb->region);
      intel_region_reference(&irb->region, intel_image->mt->region);
   }

   /* compute offset of the particular 2D image within the texture region */
   imageOffset = intel_miptree_image_offset(intel_image->mt,
                                            att->CubeMapFace,
                                            att->TextureLevel);

   if (att->Texture->Target == GL_TEXTURE_3D) {
      const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt,
                                                          att->TextureLevel);
      imageOffset += offsets[att->Zoffset];
   }

   /* store that offset in the region */
   intel_image->mt->region->draw_offset = imageOffset;

   /* update drawing region, etc */
   intel_draw_buffer(ctx, fb);
}
예제 #24
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(GLcontext * ctx,
                     struct gl_framebuffer *fb,
                     struct gl_renderbuffer_attachment *att)
{
   struct gl_texture_image *newImage
      = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
   struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);
   struct intel_texture_image *intel_image;
   GLuint dst_x, dst_y;

   (void) fb;

   ASSERT(newImage);

   intel_image = intel_texture_image(newImage);
   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);
      _mesa_render_texture(ctx, fb, att);
      return;
   }
   else if (!irb) {
      irb = intel_wrap_texture(ctx, newImage);
      if (irb) {
         /* bind the wrapper to the attachment point */
         _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base);
      }
      else {
         /* fallback to software rendering */
         _mesa_render_texture(ctx, fb, att);
         return;
      }
   }

   if (!intel_update_wrapper(ctx, irb, newImage)) {
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
       _mesa_render_texture(ctx, fb, att);
       return;
   }

   DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n",
       _glthread_GetID(),
       att->Texture->Name, newImage->Width, newImage->Height,
       irb->Base.RefCount);

   /* point the renderbufer's region to the texture image region */
   if (irb->region != intel_image->mt->region) {
      if (irb->region)
	 intel_region_release(&irb->region);
      intel_region_reference(&irb->region, intel_image->mt->region);
   }

   /* compute offset of the particular 2D image within the texture region */
   intel_miptree_get_image_offset(intel_image->mt,
				  att->TextureLevel,
				  att->CubeMapFace,
				  att->Zoffset,
				  &dst_x, &dst_y);

   intel_image->mt->region->draw_offset = (dst_y * intel_image->mt->pitch +
					   dst_x) * intel_image->mt->cpp;
   intel_image->mt->region->draw_x = dst_x;
   intel_image->mt->region->draw_y = dst_y;
   intel_image->used_as_render_target = GL_TRUE;

   /* update drawing region, etc */
   intel_draw_buffer(ctx, fb);
}