0
0
mirror of https://github.com/obsproject/obs-studio.git synced 2024-09-20 13:08:50 +02:00
obs-studio/plugins/win-capture/dc-capture.c
jp9000 f53df7da64 clang-format: Apply formatting
Code submissions have continually suffered from formatting
inconsistencies that constantly have to be addressed.  Using
clang-format simplifies this by making code formatting more consistent,
and allows automation of the code formatting so that maintainers can
focus more on the code itself instead of code formatting.
2019-06-23 23:49:10 -07:00

196 lines
4.4 KiB
C

#include "dc-capture.h"
#define WIN32_MEAN_AND_LEAN
#include <windows.h>
static inline void init_textures(struct dc_capture *capture)
{
if (capture->compatibility)
capture->texture = gs_texture_create(capture->width,
capture->height, GS_BGRA,
1, NULL, GS_DYNAMIC);
else
capture->texture =
gs_texture_create_gdi(capture->width, capture->height);
if (!capture->texture) {
blog(LOG_WARNING, "[dc_capture_init] Failed to "
"create textures");
return;
}
capture->valid = true;
}
void dc_capture_init(struct dc_capture *capture, int x, int y, uint32_t width,
uint32_t height, bool cursor, bool compatibility)
{
memset(capture, 0, sizeof(struct dc_capture));
capture->x = x;
capture->y = y;
capture->width = width;
capture->height = height;
capture->capture_cursor = cursor;
obs_enter_graphics();
if (!gs_gdi_texture_available())
compatibility = true;
capture->compatibility = compatibility;
init_textures(capture);
obs_leave_graphics();
if (!capture->valid)
return;
if (compatibility) {
BITMAPINFO bi = {0};
BITMAPINFOHEADER *bih = &bi.bmiHeader;
bih->biSize = sizeof(BITMAPINFOHEADER);
bih->biBitCount = 32;
bih->biWidth = width;
bih->biHeight = height;
bih->biPlanes = 1;
capture->hdc = CreateCompatibleDC(NULL);
capture->bmp =
CreateDIBSection(capture->hdc, &bi, DIB_RGB_COLORS,
(void **)&capture->bits, NULL, 0);
capture->old_bmp = SelectObject(capture->hdc, capture->bmp);
}
}
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 draw_cursor(struct dc_capture *capture, HDC hdc, HWND window)
{
HICON icon;
ICONINFO ii;
CURSORINFO *ci = &capture->ci;
POINT win_pos = {capture->x, capture->y};
if (!(capture->ci.flags & CURSOR_SHOWING))
return;
icon = CopyIcon(capture->ci.hCursor);
if (!icon)
return;
if (GetIconInfo(icon, &ii)) {
POINT pos;
if (window)
ClientToScreen(window, &win_pos);
pos.x = ci->ptScreenPos.x - (int)ii.xHotspot - win_pos.x;
pos.y = ci->ptScreenPos.y - (int)ii.yHotspot - win_pos.y;
DrawIconEx(hdc, pos.x, pos.y, icon, 0, 0, 0, NULL, DI_NORMAL);
DeleteObject(ii.hbmColor);
DeleteObject(ii.hbmMask);
}
DestroyIcon(icon);
}
static inline HDC dc_capture_get_dc(struct dc_capture *capture)
{
if (!capture->valid)
return NULL;
if (capture->compatibility)
return capture->hdc;
else
return gs_texture_get_dc(capture->texture);
}
static inline void dc_capture_release_dc(struct dc_capture *capture)
{
if (capture->compatibility) {
gs_texture_set_image(capture->texture, capture->bits,
capture->width * 4, false);
} else {
gs_texture_release_dc(capture->texture);
}
}
void dc_capture_capture(struct dc_capture *capture, HWND window)
{
HDC hdc_target;
HDC hdc;
if (capture->capture_cursor) {
memset(&capture->ci, 0, sizeof(CURSORINFO));
capture->ci.cbSize = sizeof(CURSORINFO);
capture->cursor_captured = GetCursorInfo(&capture->ci);
}
hdc = dc_capture_get_dc(capture);
if (!hdc) {
blog(LOG_WARNING, "[capture_screen] Failed to get "
"texture DC");
return;
}
hdc_target = GetDC(window);
BitBlt(hdc, 0, 0, capture->width, capture->height, hdc_target,
capture->x, capture->y, SRCCOPY);
ReleaseDC(NULL, hdc_target);
if (capture->cursor_captured && !capture->cursor_hidden)
draw_cursor(capture, hdc, window);
dc_capture_release_dc(capture);
capture->texture_written = true;
}
static void draw_texture(struct dc_capture *capture, gs_effect_t *effect)
{
gs_texture_t *texture = capture->texture;
gs_technique_t *tech = gs_effect_get_technique(effect, "Draw");
gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
size_t passes;
gs_effect_set_texture(image, texture);
passes = gs_technique_begin(tech);
for (size_t i = 0; i < passes; i++) {
if (gs_technique_begin_pass(tech, i)) {
if (capture->compatibility)
gs_draw_sprite(texture, GS_FLIP_V, 0, 0);
else
gs_draw_sprite(texture, 0, 0, 0);
gs_technique_end_pass(tech);
}
}
gs_technique_end(tech);
}
void dc_capture_render(struct dc_capture *capture, gs_effect_t *effect)
{
if (capture->valid && capture->texture_written)
draw_texture(capture, effect);
}