static bool texrender_resetbuffer(gs_texrender_t texrender, uint32_t cx, uint32_t cy) { if (!texrender) return false; gs_texture_destroy(texrender->target); gs_zstencil_destroy(texrender->zs); texrender->target = NULL; texrender->zs = NULL; texrender->cx = cx; texrender->cy = cy; texrender->target = gs_texture_create(cx, cy, texrender->format, 1, NULL, GS_RENDER_TARGET); if (!texrender->target) return false; if (texrender->zsformat != GS_ZS_NONE) { texrender->zs = gs_zstencil_create(cx, cy, texrender->zsformat); if (!texrender->zs) { gs_texture_destroy(texrender->target); texrender->target = NULL; return false; } } return true; }
/** * Resize the texture * * This will automatically create the texture if it does not exist * * @note requires to be called within the obs graphics context */ static inline void xshm_resize_texture(struct xshm_data *data) { if (data->texture) gs_texture_destroy(data->texture); data->texture = gs_texture_create(data->width, data->height, GS_BGRA, 1, NULL, GS_DYNAMIC); }
/** * Stop the capture */ static void xshm_capture_stop(struct xshm_data *data) { obs_enter_graphics(); if (data->texture) { gs_texture_destroy(data->texture); data->texture = NULL; } if (data->cursor) { xcb_xcursor_destroy(data->cursor); data->cursor = NULL; } obs_leave_graphics(); if (data->xshm) { xshm_xcb_detach(data->xshm); data->xshm = NULL; } if (data->xcb) { xcb_disconnect(data->xcb); data->xcb = NULL; } if (data->server) { bfree(data->server); data->server = NULL; } }
/** * Stop the capture */ static void xshm_capture_stop(struct xshm_data *data) { obs_enter_graphics(); if (data->texture) { gs_texture_destroy(data->texture); data->texture = NULL; } if (data->cursor) { xcursor_destroy(data->cursor); data->cursor = NULL; } obs_leave_graphics(); if (data->xshm) { xshm_detach(data->xshm); data->xshm = NULL; } if (data->dpy) { XSync(data->dpy, true); XCloseDisplay(data->dpy); data->dpy = NULL; } if (data->server) { bfree(data->server); data->server = NULL; } }
static void xcc_cleanup(XCompcapMain_private *p) { PLock lock(&p->lock); XDisplayLock xlock; if (p->gltex) { gs_texture_destroy(p->gltex); p->gltex = 0; } if (p->glxpixmap) { glXDestroyPixmap(xdisp, p->glxpixmap); p->glxpixmap = 0; } if (p->pixmap) { XFreePixmap(xdisp, p->pixmap); p->pixmap = 0; } if (p->win) { XCompositeUnredirectWindow(xdisp, p->win, CompositeRedirectAutomatic); XSelectInput(xdisp, p->win, 0); p->win = 0; } }
void gs_texrender_destroy(gs_texrender_t texrender) { if (texrender) { gs_texture_destroy(texrender->target); gs_zstencil_destroy(texrender->zs); bfree(texrender); } }
inline void DestroyTextures() { if (texture) { obs_enter_graphics(); gs_texture_destroy(texture); texture = nullptr; obs_leave_graphics(); } }
static void disable_deinterlacing(obs_source_t *source) { obs_enter_graphics(); gs_texture_destroy(source->async_prev_texture); gs_texrender_destroy(source->async_prev_texrender); source->deinterlace_mode = OBS_DEINTERLACE_MODE_DISABLE; source->async_prev_texture = NULL; source->async_prev_texrender = NULL; obs_leave_graphics(); }
/** * Resize the texture * * This will automatically create the texture if it does not exist */ static void xshm_resize_texture(struct xshm_data *data) { obs_enter_graphics(); if (data->texture) gs_texture_destroy(data->texture); data->texture = gs_texture_create(data->width, data->height, GS_BGRA, 1, NULL, GS_DYNAMIC); obs_leave_graphics(); }
void BrowserSource::Impl::Listener::DestroySurface( BrowserSurfaceHandle surfaceHandle) { if (textureSet.count(surfaceHandle) == 1) { obs_enter_graphics(); textureSet.erase(surfaceHandle); gs_texture_destroy(surfaceHandle); browserSource->activeTexture = nullptr; obs_leave_graphics(); } }
static void obs_free_video(void) { struct obs_core_video *video = &obs->video; if (video->video) { obs_display_free(&video->main_display); video_output_close(video->video); video->video = NULL; if (!video->graphics) return; gs_enter_context(video->graphics); if (video->mapped_surface) { gs_stagesurface_unmap(video->mapped_surface); video->mapped_surface = NULL; } for (size_t i = 0; i < NUM_TEXTURES; i++) { gs_stagesurface_destroy(video->copy_surfaces[i]); gs_texture_destroy(video->render_textures[i]); gs_texture_destroy(video->convert_textures[i]); gs_texture_destroy(video->output_textures[i]); obs_source_frame_free(&video->convert_frames[i]); video->copy_surfaces[i] = NULL; video->render_textures[i] = NULL; video->convert_textures[i] = NULL; video->output_textures[i] = NULL; } gs_leave_context(); circlebuf_free(&video->timestamp_buffer); video->cur_texture = 0; } }
void dc_capture_free(struct dc_capture *capture) { if (capture->hdc) { SelectObject(capture->hdc, capture->old_bmp); DeleteDC(capture->hdc); DeleteObject(capture->bmp); } obs_enter_graphics(); gs_texture_destroy(capture->texture); obs_leave_graphics(); memset(capture, 0, sizeof(struct dc_capture)); }
static void ft2_source_destroy(void *data) { struct ft2_source *srcdata = data; if (srcdata->font_face != NULL) { FT_Done_Face(srcdata->font_face); srcdata->font_face = NULL; } for (uint32_t i = 0; i < num_cache_slots; i++) { if (srcdata->cacheglyphs[i] != NULL) { bfree(srcdata->cacheglyphs[i]); srcdata->cacheglyphs[i] = NULL; } } if (srcdata->font_name != NULL) bfree(srcdata->font_name); if (srcdata->font_style != NULL) bfree(srcdata->font_style); if (srcdata->text != NULL) bfree(srcdata->text); if (srcdata->texbuf != NULL) bfree(srcdata->texbuf); if (srcdata->colorbuf != NULL) bfree(srcdata->colorbuf); if (srcdata->text_file != NULL) bfree(srcdata->text_file); obs_enter_graphics(); if (srcdata->tex != NULL) { gs_texture_destroy(srcdata->tex); srcdata->tex = NULL; } if (srcdata->vbuf != NULL) { gs_vertexbuffer_destroy(srcdata->vbuf); srcdata->vbuf = NULL; } if (srcdata->draw_effect != NULL) { gs_effect_destroy(srcdata->draw_effect); srcdata->draw_effect = NULL; } obs_leave_graphics(); bfree(srcdata); }
XCompcapMain::~XCompcapMain() { ObsGsContextHolder obsctx; if (p->tex) { gs_texture_destroy(p->tex); p->tex = 0; } xcc_cleanup(p); if (p->cursor) { xcursor_destroy(p->cursor); p->cursor = nullptr; } delete p; }
void gs_image_file_free(gs_image_file_t *image) { if (!image) return; if (image->loaded) { if (image->is_animated_gif) { gif_finalise(&image->gif); bfree(image->animation_frame_cache); bfree(image->animation_frame_data); } gs_texture_destroy(image->texture); } bfree(image->texture_data); bfree(image->gif_data); memset(image, 0, sizeof(*image)); }
/* * Create the cursor texture, either by updating if the new cursor has the same * size or by creating a new texture if the size is different */ static void xcursor_create(xcursor_t *data, XFixesCursorImage *xc) { uint32_t *pixels = xcursor_pixels(xc); if (data->tex && data->last_height == xc->width && data->last_width == xc->height) { gs_texture_set_image(data->tex, (const uint8_t *) pixels, xc->width * sizeof(uint32_t), False); } else { if (data->tex) gs_texture_destroy(data->tex); data->tex = gs_texture_create(xc->width, xc->height, GS_BGRA, 1, (const uint8_t **) &pixels, GS_DYNAMIC); } bfree(pixels); data->last_serial = xc->cursor_serial; data->last_width = xc->width; data->last_height = xc->height; }
/** * Destroy the capture */ static void xshm_destroy(void *vptr) { XSHM_DATA(vptr); if (!data) return; obs_enter_graphics(); if (data->texture) gs_texture_destroy(data->texture); if (data->cursor) xcursor_destroy(data->cursor); obs_leave_graphics(); if (data->xshm) xshm_detach(data->xshm); if (data->dpy) XCloseDisplay(data->dpy); bfree(data); }
/* * Create the cursor texture, either by updating if the new cursor has the same * size or by creating a new texture if the size is different */ static void xcb_xcursor_create(xcb_xcursor_t *data, xcb_xfixes_get_cursor_image_reply_t *xc) { uint32_t *pixels = xcb_xfixes_get_cursor_image_cursor_image(xc); if (!pixels) return; if (data->tex && data->last_height == xc->width && data->last_width == xc->height) { gs_texture_set_image(data->tex, (const uint8_t *) pixels, xc->width * sizeof(uint32_t), false); } else { if (data->tex) gs_texture_destroy(data->tex); data->tex = gs_texture_create(xc->width, xc->height, GS_BGRA, 1, (const uint8_t **) &pixels, GS_DYNAMIC); } data->last_serial = xc->cursor_serial; data->last_width = xc->width; data->last_height = xc->height; }
void xcursor_destroy(xcursor_t *data) { if (data->tex) gs_texture_destroy(data->tex); bfree(data); }
void cache_glyphs(struct ft2_source *srcdata, wchar_t *cache_glyphs) { FT_GlyphSlot slot = 0; FT_UInt glyph_index = 0; if (!srcdata->font_face || !cache_glyphs) return; //slot = srcdata->font_face->glyph; uint32_t dx = srcdata->texbuf_x, dy = srcdata->texbuf_y; uint8_t alpha; int32_t cached_glyphs = 0; size_t len = wcslen(cache_glyphs); for (size_t i = 0; i < len; i++) { FT_Face curFace; glyph_index = FT_Get_Char_Index_Fallback(srcdata, &curFace, cache_glyphs[i]); if (curFace == 0) goto skip_glyph; slot = curFace->glyph; if (src_glyph != NULL) goto skip_glyph; FT_Load_Glyph(curFace, glyph_index, FT_LOAD_DEFAULT); bool isUseFallback = slot->face == srcdata->fallback_face; bool shouldBolden = ((!isUseFallback && srcdata->fake_bold) || (isUseFallback && srcdata->fallback_fake_bold)); if (slot->format == FT_GLYPH_FORMAT_OUTLINE && shouldBolden) FT_Outline_EmboldenXY(&slot->outline, 0x80, 0x40); FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL); uint32_t g_w = slot->bitmap.width; uint32_t g_h = slot->bitmap.rows; if (srcdata->max_h < g_h) srcdata->max_h = g_h; if (dx + g_w >= texbuf_w) { dx = 0; dy += srcdata->max_h + 1; } src_glyph = bzalloc(sizeof(struct glyph_info)); src_glyph->u = (float)dx / (float)texbuf_w; src_glyph->u2 = (float)(dx + g_w) / (float)texbuf_w; src_glyph->v = (float)dy / (float)texbuf_h; src_glyph->v2 = (float)(dy + g_h) / (float)texbuf_h; src_glyph->w = g_w; src_glyph->h = g_h; src_glyph->yoff = slot->bitmap_top; src_glyph->xoff = slot->bitmap_left; src_glyph->xadv = slot->advance.x >> 6; for (uint32_t y = 0; y < g_h; y++) { for (uint32_t x = 0; x < g_w; x++) { alpha = slot->bitmap.buffer[glyph_pos]; srcdata->texbuf[buf_pos] = 0x00FFFFFF ^ ((uint32_t)alpha << 24); } } dx += (g_w + 1); if (dx >= texbuf_w) { dx = 0; dy += srcdata->max_h; } cached_glyphs++; skip_glyph:; } srcdata->texbuf_x = dx; srcdata->texbuf_y = dy; if (cached_glyphs > 0) { obs_enter_graphics(); if (srcdata->tex != NULL) { gs_texture_t *tmp_texture = NULL; tmp_texture = srcdata->tex; srcdata->tex = NULL; gs_texture_destroy(tmp_texture); } srcdata->tex = gs_texture_create(texbuf_w, texbuf_h, GS_RGBA, 1, (const uint8_t **)&srcdata->texbuf, 0); obs_leave_graphics(); } }
void cache_glyphs(struct ft2_source *srcdata, wchar_t *cache_glyphs) { FT_GlyphSlot slot; FT_UInt glyph_index = 0; if (!srcdata->font_face) return; slot = srcdata->font_face->glyph; uint32_t dx = srcdata->texbuf_x, dy = srcdata->texbuf_y; uint8_t alpha; int32_t cached_glyphs = 0; for (uint32_t i = 0; i < wcslen(cache_glyphs); i++) { glyph_index = FT_Get_Char_Index(srcdata->font_face, cache_glyphs[i]); if (src_glyph != NULL) goto skip_glyph; FT_Load_Glyph(srcdata->font_face, glyph_index, FT_LOAD_DEFAULT); FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL); uint32_t g_w = slot->bitmap.width; uint32_t g_h = slot->bitmap.rows; if (srcdata->max_h < g_h) srcdata->max_h = g_h; if (dx + g_w >= texbuf_w) { dx = 0; dy += srcdata->max_h + 1; } src_glyph = bzalloc(sizeof(struct glyph_info)); src_glyph->u = (float)dx / (float)texbuf_w; src_glyph->u2 = (float)(dx + g_w) / (float)texbuf_w; src_glyph->v = (float)dy / (float)texbuf_h; src_glyph->v2 = (float)(dy + g_h) / (float)texbuf_h; src_glyph->w = g_w; src_glyph->h = g_h; src_glyph->yoff = slot->bitmap_top; src_glyph->xoff = slot->bitmap_left; src_glyph->xadv = slot->advance.x >> 6; for (uint32_t y = 0; y < g_h; y++) { for (uint32_t x = 0; x < g_w; x++) { alpha = slot->bitmap.buffer[glyph_pos]; srcdata->texbuf[buf_pos] = 0x00FFFFFF ^ (alpha << 24); } } dx += (g_w + 1); if (dx >= texbuf_w) { dx = 0; dy += srcdata->max_h; } cached_glyphs++; skip_glyph:; } srcdata->texbuf_x = dx; srcdata->texbuf_y = dy; if (cached_glyphs > 0) { obs_enter_graphics(); if (srcdata->tex != NULL) { gs_texture_t tmp_texture = NULL; tmp_texture = srcdata->tex; srcdata->tex = NULL; gs_texture_destroy(tmp_texture); } srcdata->tex = gs_texture_create(texbuf_w, texbuf_h, GS_RGBA, 1, (const uint8_t **)&srcdata->texbuf, 0); obs_leave_graphics(); } }
void XCompcapMain::updateSettings(obs_data_t *settings) { PLock lock(&p->lock); XErrorLock xlock; ObsGsContextHolder obsctx; blog(LOG_DEBUG, "Settings updating"); Window prevWin = p->win; xcc_cleanup(p); if (settings) { const char *windowName = obs_data_get_string(settings, "capture_window"); p->windowName = windowName; p->win = getWindowFromString(windowName); p->cut_top = obs_data_get_int(settings, "cut_top"); p->cut_left = obs_data_get_int(settings, "cut_left"); p->cut_right = obs_data_get_int(settings, "cut_right"); p->cut_bot = obs_data_get_int(settings, "cut_bot"); p->lockX = obs_data_get_bool(settings, "lock_x"); p->swapRedBlue = obs_data_get_bool(settings, "swap_redblue"); p->show_cursor = obs_data_get_bool(settings, "show_cursor"); p->include_border = obs_data_get_bool(settings, "include_border"); p->exclude_alpha = obs_data_get_bool(settings, "exclude_alpha"); } else { p->win = prevWin; } xlock.resetError(); if (p->win) XCompositeRedirectWindow(xdisp, p->win, CompositeRedirectAutomatic); if (xlock.gotError()) { blog(LOG_ERROR, "XCompositeRedirectWindow failed: %s", xlock.getErrorText().c_str()); return; } if (p->win) XSelectInput(xdisp, p->win, StructureNotifyMask | ExposureMask); XSync(xdisp, 0); XWindowAttributes attr; if (!p->win || !XGetWindowAttributes(xdisp, p->win, &attr)) { p->win = 0; p->width = 0; p->height = 0; return; } if (p->win && p->cursor && p->show_cursor) { Window child; int x, y; XTranslateCoordinates(xdisp, p->win, attr.root, 0, 0, &x, &y, &child); xcursor_offset(p->cursor, x, y); } gs_color_format cf = GS_RGBA; if (p->exclude_alpha) { cf = GS_BGRX; } p->border = attr.border_width; if (p->include_border) { p->width = attr.width + p->border * 2; p->height = attr.height + p->border * 2; } else { p->width = attr.width; p->height = attr.height; } if (p->cut_top + p->cut_bot < (int)p->height) { p->cur_cut_top = p->cut_top; p->cur_cut_bot = p->cut_bot; } else { p->cur_cut_top = 0; p->cur_cut_bot = 0; } if (p->cut_left + p->cut_right < (int)p->width) { p->cur_cut_left = p->cut_left; p->cur_cut_right = p->cut_right; } else { p->cur_cut_left = 0; p->cur_cut_right = 0; } if (p->tex) gs_texture_destroy(p->tex); uint8_t *texData = new uint8_t[width() * height() * 4]; memset(texData, 0, width() * height() * 4); const uint8_t* texDataArr[] = { texData, 0 }; p->tex = gs_texture_create(width(), height(), cf, 1, texDataArr, 0); delete[] texData; if (p->swapRedBlue) { GLuint tex = *(GLuint*)gs_texture_get_obj(p->tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE); glBindTexture(GL_TEXTURE_2D, 0); } const int attrs[] = { GLX_BIND_TO_TEXTURE_RGBA_EXT, GL_TRUE, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, GLX_DOUBLEBUFFER, GL_FALSE, None }; int nelem = 0; GLXFBConfig* configs = glXChooseFBConfig(xdisp, XCompcap::getRootWindowScreen(attr.root), attrs, &nelem); if (nelem <= 0) { blog(LOG_ERROR, "no matching fb config found"); p->win = 0; p->height = 0; p->width = 0; return; } glXGetFBConfigAttrib(xdisp, configs[0], GLX_Y_INVERTED_EXT, &nelem); p->inverted = nelem != 0; xlock.resetError(); p->pixmap = XCompositeNameWindowPixmap(xdisp, p->win); if (xlock.gotError()) { blog(LOG_ERROR, "XCompositeNameWindowPixmap failed: %s", xlock.getErrorText().c_str()); p->pixmap = 0; XFree(configs); return; } const int attribs[] = { GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, None }; p->glxpixmap = glXCreatePixmap(xdisp, configs[0], p->pixmap, attribs); if (xlock.gotError()) { blog(LOG_ERROR, "glXCreatePixmap failed: %s", xlock.getErrorText().c_str()); XFreePixmap(xdisp, p->pixmap); XFree(configs); p->pixmap = 0; p->glxpixmap = 0; return; } XFree(configs); p->gltex = gs_texture_create(p->width, p->height, cf, 1, 0, GS_GL_DUMMYTEX); GLuint gltex = *(GLuint*)gs_texture_get_obj(p->gltex); glBindTexture(GL_TEXTURE_2D, gltex); glXBindTexImageEXT(xdisp, p->glxpixmap, GLX_FRONT_LEFT_EXT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); }