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; }
void agp_resize_vstore(struct storage_info_t* s, size_t w, size_t h) { struct agp_fenv* env = agp_env(); s->w = w; s->h = h; s->bpp = sizeof(av_pixel); alloc_buffer(s); rebuild_pbo(s); agp_update_vstore(s, true); }
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) { 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; }
struct stream_meta agp_stream_prepare(struct storage_info_t* s, struct stream_meta meta, enum stream_type type) { struct agp_fenv* env = agp_env(); struct stream_meta res = meta; res.state = true; res.type = type; switch (type){ case STREAM_RAW: if (!s->vinf.text.wid) setup_unpack_pbo(s, NULL); alloc_buffer(s); res.buf = s->vinf.text.raw; res.state = res.buf != NULL; break; case STREAM_RAW_DIRECT_COPY: alloc_buffer(s); case STREAM_RAW_DIRECT: if (!s->vinf.text.wid) setup_unpack_pbo(s, meta.buf); if (meta.dirty) pbo_stream_sub(s, meta.buf, &meta, type == STREAM_RAW_DIRECT_COPY); else pbo_stream(s, meta.buf, &meta, type == STREAM_RAW_DIRECT_COPY); break; /* resynch: drop PBOs and GLid, alloc / upload and rebuild possible PBOs */ case STREAM_EXT_RESYNCH: agp_null_vstore(s); agp_update_vstore(s, true); rebuild_pbo(s); break; case STREAM_RAW_DIRECT_SYNCHRONOUS: agp_activate_vstore(s); if (meta.dirty){ set_pixel_store(s->w, meta); env->tex_subimage_2d(GL_TEXTURE_2D, 0, meta.x1, meta.y1, meta.w, meta.h, s->vinf.text.s_fmt ? s->vinf.text.s_fmt : GL_PIXEL_FORMAT, GL_UNSIGNED_BYTE, meta.buf ); reset_pixel_store(); } else env->tex_subimage_2d(GL_TEXTURE_2D, 0, 0, 0, s->w, s->h, s->vinf.text.s_fmt ? s->vinf.text.s_fmt : GL_PIXEL_FORMAT, GL_UNSIGNED_BYTE, meta.buf ); agp_deactivate_vstore(); break; case STREAM_HANDLE: /* if platform_video_map_handle fails here, prepare an empty vstore and attempt * again, if that succeeds it means that we had to go through a RTT * indirection, if that fails we should convey back to the client that we can't accept this kind of transfer */ res.state = platform_video_map_handle(s, meta.handle); break; } return res; }