Beispiel #1
0
void agp_resize_rendertarget(
	struct agp_rendertarget* tgt, size_t neww, size_t newh)
{
	if (!tgt || !tgt->store){
		arcan_warning("attempted resize on broken rendertarget\n");
		return;
	}

/* same dimensions, no need to resize */
	if (tgt->store->w == neww && tgt->store->h == newh)
		return;

	erase_store(tgt->store);
	erase_store(tgt->store_back);

	struct agp_fenv* env = agp_env();

	agp_empty_vstore(tgt->store, neww, newh);
	if (tgt->store_back)
		agp_empty_vstore(tgt->store_back, neww, newh);

/* we inplace- modify, want the refcounter intact */
	env->delete_framebuffers(1,&tgt->fbo);
	env->delete_renderbuffers(1,&tgt->depth);
	tgt->fbo = GL_NONE;
	tgt->depth = GL_NONE;
	alloc_fbo(tgt, false);
}
Beispiel #2
0
void agp_resize_rendertarget(
	struct agp_rendertarget* tgt, size_t neww, size_t newh)
{
	if (!tgt || !tgt->store){
		arcan_warning("attempted resize on broken rendertarget\n");
		return;
	}

/* same dimensions, no need to resize */
	if (tgt->store->w == neww && tgt->store->h == newh)
		return;

	struct storage_info_t* os = tgt->store;

/* we inplace- modify, want the refcounter intact */
	agp_null_vstore(os);
	arcan_mem_free(os->vinf.text.raw);
	os->vinf.text.raw = NULL;
	os->vinf.text.s_raw = 0;
	agp_empty_vstore(os, neww, newh);

	glDeleteFramebuffers(1,&tgt->fbo);
	glDeleteRenderbuffers(1,&tgt->depth);
	tgt->fbo = GL_NONE;
	tgt->depth = GL_NONE;
	alloc_fbo(tgt, tgt->mode);
}
Beispiel #3
0
struct agp_rendertarget* agp_setup_rendertarget(struct storage_info_t* vstore,
	enum rendertarget_mode m)
{
	struct agp_rendertarget* r = arcan_alloc_mem(sizeof(struct agp_rendertarget),
		ARCAN_MEM_VSTRUCT, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_NATURAL);

	r->store = vstore;
	r->mode = m;

	alloc_fbo(r, false);
	return r;
}
Beispiel #4
0
struct agp_rendertarget* agp_setup_rendertarget(
	struct storage_info_t* vstore, enum rendertarget_mode m)
{
	struct agp_rendertarget* r = arcan_alloc_mem(sizeof(struct agp_rendertarget),
		ARCAN_MEM_VSTRUCT, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_NATURAL);

	r->store = vstore;
	r->mode = m;
	r->clearcol[3] = 1.0;

/* need this tracking because there's no external memory management for _back */
	r->front_active = true;

	if (m & RENDERTARGET_DOUBLEBUFFER){
		r->store_back = arcan_alloc_mem(sizeof(struct storage_info_t),
			ARCAN_MEM_VSTRUCT, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_NATURAL);
		r->store_back->vinf.text.s_fmt = vstore->vinf.text.s_fmt;
		r->store_back->vinf.text.d_fmt = vstore->vinf.text.d_fmt;
		agp_empty_vstore(r->store_back, vstore->w, vstore->h);
	}

	alloc_fbo(r, false);
	return r;
}
Beispiel #5
0
static bool alloc_fbo(struct agp_rendertarget* dst, bool retry)
{
	struct agp_fenv* env = agp_env();
	env->gen_framebuffers(1, &dst->fbo);
	int mode = dst->mode & (~RENDERTARGET_DOUBLEBUFFER);

/* need both stencil and depth buffer, but we don't need the data from them */
	env->bind_framebuffer(GL_FRAMEBUFFER, dst->fbo);

	if (mode > RENDERTARGET_DEPTH)
	{
		env->framebuffer_texture_2d(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
			GL_TEXTURE_2D, dst->store->vinf.text.glid, 0);

/* need a Z buffer in the offscreen rendering but don't want
 * bo store it, so setup a renderbuffer */
		if (mode > RENDERTARGET_COLOR){
			env->gen_renderbuffers(1, &dst->depth);

/* could use GL_DEPTH_COMPONENT only if we'd know that there
 * wouldn't be any clipping in the active rendertarget */
			if (!retry){
				env->bind_renderbuffer(GL_RENDERBUFFER, dst->depth);
				env->renderbuffer_storage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
					dst->store->w, dst->store->h);
				env->bind_renderbuffer(GL_RENDERBUFFER, 0);
				env->framebuffer_renderbuffer(GL_FRAMEBUFFER,
					GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, dst->depth);
			}
		}
	}
	else {
/* DEPTH buffer only (shadowmapping, ...) convert the storage to
 * contain a depth texture */
		size_t w = dst->store->w;
		size_t h = dst->store->h;

		agp_drop_vstore(dst->store);

		struct storage_info_t* store = dst->store;

		memset(store, '\0', sizeof(struct storage_info_t));

		store->txmapped   = TXSTATE_DEPTH;
		store->txu        = ARCAN_VTEX_CLAMP;
		store->txv        = ARCAN_VTEX_CLAMP;
		store->scale      = ARCAN_VIMAGE_NOPOW2;
		store->imageproc  = IMAGEPROC_NORMAL;
		store->filtermode = ARCAN_VFILTER_NONE;
		store->refcount   = 1;
		store->w = w;
		store->h = h;

/* generate ID etc. special path for TXSTATE_DEPTH */
		agp_update_vstore(store, true);

		env->draw_buffer(GL_NONE);
		env->read_buffer(GL_NONE);

		env->framebuffer_texture_2d(GL_FRAMEBUFFER,
			GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, store->vinf.text.glid, 0);
	}

/* basic error handling / status checking
 * may be possible that we should cache this in the
 * rendertarget and only call when / if something changes as
 * it's not certain that drivers won't stall the pipeline on this */
	GLenum status = env->check_framebuffer(GL_FRAMEBUFFER);
	if (status != GL_FRAMEBUFFER_COMPLETE){
		arcan_warning("FBO support broken, couldn't create basic FBO:\n");
		switch(status){
		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
			if (!retry){
				arcan_warning("\t Incomplete Attachment, attempting "
					"simple framebuffer, this will likely break 3D and complex"
					"clipping operations.\n");
				return alloc_fbo(dst, true);
			}
			else
				arcan_warning("\t Simple attachement broke as well "
					"likely driver issue.\n");
		break;

#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
			arcan_warning("\t Not all attached buffers have "
				"the same dimensions.\n");
		break;
#endif

		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
			arcan_warning("\t One or several FBO attachment points are missing.\n");
		break;

		case GL_FRAMEBUFFER_UNSUPPORTED:
			arcan_warning("\t Request formats combination unsupported.\n");
		break;
		}

		if (dst->fbo != GL_NONE)
			env->delete_framebuffers(1,&dst->fbo);
		if (dst->depth != GL_NONE)
			env->delete_renderbuffers(1,&dst->depth);

		dst->fbo = dst->depth = GL_NONE;
		return false;
	}

	env->bind_framebuffer(GL_FRAMEBUFFER, 0);
	return true;
}