void agp_empty_vstore(struct storage_info_t* vs, size_t w, size_t h) { size_t sz = w * h * sizeof(av_pixel); vs->vinf.text.s_raw = sz; /* this is to allow an override of s_fmt and still handle reset */ if (vs->vinf.text.s_fmt == 0) vs->vinf.text.s_fmt = GL_PIXEL_FORMAT; if (vs->vinf.text.d_fmt == 0) vs->vinf.text.d_fmt = GL_STORE_PIXEL_FORMAT; vs->vinf.text.raw = arcan_alloc_mem( vs->vinf.text.s_raw, ARCAN_MEM_VBUFFER, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_PAGE ); vs->w = w; vs->h = h; vs->bpp = sizeof(av_pixel); vs->txmapped = TXSTATE_TEX2D; agp_update_vstore(vs, true); arcan_mem_free(vs->vinf.text.raw); vs->vinf.text.raw = 0; vs->vinf.text.s_raw = 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; }
static void alloc_buffer(struct storage_info_t* s) { if (s->vinf.text.s_raw != s->w * s->h * sizeof(av_pixel)){ arcan_mem_free(s->vinf.text.raw); s->vinf.text.raw = NULL; } if (!s->vinf.text.raw){ s->vinf.text.s_raw = s->w * s->h * sizeof(av_pixel); s->vinf.text.raw = arcan_alloc_mem(s->vinf.text.s_raw, ARCAN_MEM_VBUFFER, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_PAGE); } }
/* * Allocate memory intended for read-only or * exec use (JIT, ...) */ void* arcan_alloc_fillmem(const void* data, size_t ds, enum arcan_memtypes type, enum arcan_memhint hint, enum arcan_memalign align) { void* buf = arcan_alloc_mem(ds, type, hint, align); if (!buf) return NULL; memcpy(buf, data, ds); return buf; }
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; }
struct agp_fenv* agp_alloc_fenv( void*(lookup)(void* tag, const char* sym, bool req), void* tag) { struct agp_fenv* fenv = arcan_alloc_mem( sizeof(struct agp_fenv), ARCAN_MEM_VSTRUCT, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_NATURAL ); /* FIXME: * need a WRITELOCK flag to the allocation and calls to writelock afterwards */ agp_glinit_fenv(fenv, lookup ? lookup : lookup_fun, tag); if (!agp_env()) agp_setenv(fenv); return fenv; }
void agp_empty_vstore(struct storage_info_t* vs, size_t w, size_t h) { size_t sz = w * h * sizeof(av_pixel); vs->vinf.text.s_raw = sz; vs->vinf.text.raw = arcan_alloc_mem( vs->vinf.text.s_raw, ARCAN_MEM_VBUFFER, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_PAGE ); vs->w = w; vs->h = h; vs->txmapped = TXSTATE_TEX2D; agp_update_vstore(vs, true); arcan_mem_free(vs->vinf.text.raw); vs->vinf.text.raw = 0; vs->vinf.text.s_raw = 0; }
static bool alloc_fbo(struct agp_rendertarget* dst, bool retry) { glGenFramebuffers(1, &dst->fbo); /* need both stencil and depth buffer, but we don't need the data from them */ glBindFramebuffer(GL_FRAMEBUFFER, dst->fbo); if (dst->mode > RENDERTARGET_DEPTH) { glFramebufferTexture2D(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 (dst->mode > RENDERTARGET_COLOR) { glGenRenderbuffers(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){ glBindRenderbuffer(GL_RENDERBUFFER, dst->depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, dst->store->w, dst->store->h); glFramebufferRenderbuffer(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); dst->store = arcan_alloc_mem(sizeof(struct storage_info_t), ARCAN_MEM_VSTRUCT, 0, ARCAN_MEMALIGN_NATURAL); 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); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glFramebufferTexture2D(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 = glCheckFramebufferStatus(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) glDeleteFramebuffers(1,&dst->fbo); if (dst->depth != GL_NONE) glDeleteRenderbuffers(1,&dst->depth); dst->fbo = dst->depth = GL_NONE; return false; } glBindFramebuffer(GL_FRAMEBUFFER, 0); return true; }