Fix transparency?
This commit is contained in:
@@ -115,4 +115,9 @@ if(BUILD_TESTING)
|
||||
$<TARGET_FILE:obs-webkit-browser> "${CMAKE_CURRENT_SOURCE_DIR}/data"
|
||||
$<TARGET_FILE:obs-webkit-renderer> audio-test)
|
||||
set_tests_properties(module-audio-test PROPERTIES TIMEOUT 20 SKIP_RETURN_CODE 77)
|
||||
|
||||
add_test(NAME module-alpha-test COMMAND module-load-test
|
||||
$<TARGET_FILE:obs-webkit-browser> "${CMAKE_CURRENT_SOURCE_DIR}/data"
|
||||
$<TARGET_FILE:obs-webkit-renderer> alpha-test)
|
||||
set_tests_properties(module-alpha-test PROPERTIES TIMEOUT 20 SKIP_RETURN_CODE 77)
|
||||
endif()
|
||||
|
||||
@@ -684,7 +684,8 @@ static struct obs_source_info browser_info = {
|
||||
.id = "webkit_browser_source",
|
||||
.type = OBS_SOURCE_TYPE_INPUT,
|
||||
.icon_type = OBS_ICON_TYPE_BROWSER,
|
||||
.output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | OBS_SOURCE_INTERACTION,
|
||||
.output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | OBS_SOURCE_INTERACTION |
|
||||
OBS_SOURCE_SRGB,
|
||||
.get_name = browser_name,
|
||||
.create = browser_create,
|
||||
.destroy = browser_destroy,
|
||||
|
||||
@@ -19,6 +19,56 @@ struct audio_probe {
|
||||
atomic_bool signal;
|
||||
};
|
||||
|
||||
static bool source_alpha_is_correct(obs_source_t *source)
|
||||
{
|
||||
bool correct = false;
|
||||
uint8_t solid[4] = {0};
|
||||
uint8_t half[4] = {0};
|
||||
uint8_t background[4] = {0};
|
||||
obs_set_output_source(0, source);
|
||||
for (unsigned attempt = 0; attempt < 60 && !correct; attempt++) {
|
||||
usleep(100000);
|
||||
obs_enter_graphics();
|
||||
gs_texrender_t *target = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
gs_stagesurf_t *stage = gs_stagesurface_create(64, 64, GS_BGRA);
|
||||
if (target && stage && gs_texrender_begin(target, 64, 64)) {
|
||||
struct vec4 clear = {0};
|
||||
gs_clear(GS_CLEAR_COLOR, &clear, 0.0f, 0);
|
||||
gs_ortho(0.0f, 64.0f, 0.0f, 64.0f, -100.0f, 100.0f);
|
||||
bool previous_srgb = gs_set_linear_srgb(true);
|
||||
obs_source_video_render(source);
|
||||
gs_set_linear_srgb(previous_srgb);
|
||||
gs_texrender_end(target);
|
||||
gs_stage_texture(stage, gs_texrender_get_texture(target));
|
||||
uint8_t *pixels = NULL;
|
||||
uint32_t stride = 0;
|
||||
if (gs_stagesurface_map(stage, &pixels, &stride)) {
|
||||
memcpy(background, pixels, sizeof(background));
|
||||
memcpy(solid, pixels + (size_t)24 * stride + 24 * 4, sizeof(solid));
|
||||
memcpy(half, pixels + (size_t)40 * stride + 40 * 4, sizeof(half));
|
||||
gs_stagesurface_unmap(stage);
|
||||
correct = solid[0] < 32 && solid[1] < 40 && solid[2] > 225 &&
|
||||
solid[3] == 255 && half[0] < 8 && half[1] < 8 &&
|
||||
half[2] > 120 && half[2] < 136 && half[3] > 120 &&
|
||||
half[3] < 136 && background[0] == 0 &&
|
||||
background[1] == 0 && background[2] == 0 &&
|
||||
background[3] == 0;
|
||||
}
|
||||
}
|
||||
gs_stagesurface_destroy(stage);
|
||||
gs_texrender_destroy(target);
|
||||
obs_leave_graphics();
|
||||
}
|
||||
obs_set_output_source(0, NULL);
|
||||
if (!correct)
|
||||
fprintf(stderr,
|
||||
"OBS compositing changed browser alpha (solid BGRA=%u,%u,%u,%u; "
|
||||
"half BGRA=%u,%u,%u,%u; background BGRA=%u,%u,%u,%u)\n",
|
||||
solid[0], solid[1], solid[2], solid[3], half[0], half[1], half[2],
|
||||
half[3], background[0], background[1], background[2], background[3]);
|
||||
return correct;
|
||||
}
|
||||
|
||||
static bool write_all(int fd, const void *data, size_t size)
|
||||
{
|
||||
const uint8_t *cursor = data;
|
||||
@@ -149,10 +199,13 @@ static void audio_captured(void *opaque, obs_source_t *source,
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 4 || argc > 5) {
|
||||
fprintf(stderr, "usage: %s plugin.so data-directory renderer [audio-test]\n", argv[0]);
|
||||
fprintf(stderr,
|
||||
"usage: %s plugin.so data-directory renderer [audio-test | alpha-test]\n",
|
||||
argv[0]);
|
||||
return 2;
|
||||
}
|
||||
bool audio_test = argc == 5 && strcmp(argv[4], "audio-test") == 0;
|
||||
bool alpha_test = argc == 5 && strcmp(argv[4], "alpha-test") == 0;
|
||||
char temporary[] = "/tmp/obs-webkit-module-test-XXXXXX";
|
||||
if (!mkdtemp(temporary)) {
|
||||
perror("mkdtemp");
|
||||
@@ -180,6 +233,26 @@ int main(int argc, char **argv)
|
||||
obs_shutdown();
|
||||
return 77;
|
||||
}
|
||||
if (alpha_test) {
|
||||
struct obs_video_info video_info = {
|
||||
.graphics_module = "libobs-opengl",
|
||||
.fps_num = 30,
|
||||
.fps_den = 1,
|
||||
.base_width = 64,
|
||||
.base_height = 64,
|
||||
.output_width = 64,
|
||||
.output_height = 64,
|
||||
.output_format = VIDEO_FORMAT_BGRA,
|
||||
.gpu_conversion = false,
|
||||
.colorspace = VIDEO_CS_DEFAULT,
|
||||
.range = VIDEO_RANGE_FULL,
|
||||
.scale_type = OBS_SCALE_DISABLE,
|
||||
};
|
||||
if (obs_reset_video(&video_info) != OBS_VIDEO_SUCCESS) {
|
||||
obs_shutdown();
|
||||
return 77;
|
||||
}
|
||||
}
|
||||
char audio_url[128] = {0};
|
||||
pid_t audio_server = audio_test ? start_audio_server(audio_url, sizeof(audio_url)) : -1;
|
||||
if (audio_test && audio_server < 0) {
|
||||
@@ -200,17 +273,28 @@ int main(int argc, char **argv)
|
||||
const char *name = obs_source_get_display_name("webkit_browser_source");
|
||||
uint32_t flags = obs_get_source_output_flags("webkit_browser_source");
|
||||
bool valid = name && strstr(name, "WebKit") && (flags & OBS_SOURCE_ASYNC_VIDEO) &&
|
||||
(flags & OBS_SOURCE_AUDIO) && (flags & OBS_SOURCE_INTERACTION);
|
||||
(flags & OBS_SOURCE_AUDIO) && (flags & OBS_SOURCE_INTERACTION) &&
|
||||
(flags & OBS_SOURCE_SRGB);
|
||||
if (!valid)
|
||||
fprintf(stderr, "source registration is incomplete (name=%s, flags=0x%x)\n",
|
||||
name ? name : "(null)", flags);
|
||||
obs_data_t *settings = obs_data_create();
|
||||
obs_data_set_string(settings, "url", audio_test ? audio_url :
|
||||
"data:text/html,<body style='background:red'></body>");
|
||||
const char *test_url = "data:text/html,<body style='background:red'></body>";
|
||||
if (audio_test)
|
||||
test_url = audio_url;
|
||||
else if (alpha_test)
|
||||
test_url = "data:text/html,<body><div id='box'></div></body>";
|
||||
obs_data_set_string(settings, "url", test_url);
|
||||
if (alpha_test)
|
||||
obs_data_set_string(settings, "css",
|
||||
"html,body{margin:0}#box{position:fixed;left:16px;top:16px;"
|
||||
"width:16px;height:16px;background:rgb(241,23,17)}"
|
||||
"#box:after{content:'';position:fixed;left:32px;top:32px;"
|
||||
"width:16px;height:16px;background:rgba(255,0,0,.5)}");
|
||||
obs_data_set_int(settings, "width", 64);
|
||||
obs_data_set_int(settings, "height", 64);
|
||||
obs_data_set_int(settings, "fps", 10);
|
||||
obs_data_set_int(settings, "zoom", 175);
|
||||
obs_data_set_int(settings, "zoom", alpha_test ? 100 : 175);
|
||||
obs_data_set_bool(settings, "capture_audio", audio_test);
|
||||
obs_data_set_bool(settings, "transparent", true);
|
||||
obs_data_set_bool(settings, "hardware_acceleration", false);
|
||||
@@ -244,6 +328,8 @@ int main(int argc, char **argv)
|
||||
if (source && audio_test)
|
||||
obs_source_add_audio_capture_callback(source, audio_captured, &probe);
|
||||
if (source) {
|
||||
if (alpha_test && !source_alpha_is_correct(source))
|
||||
valid = false;
|
||||
unsigned attempts = audio_test ? 100 : 5;
|
||||
for (unsigned attempt = 0; attempt < attempts &&
|
||||
(!audio_test || !atomic_load(&probe.signal)); attempt++)
|
||||
|
||||
@@ -104,8 +104,12 @@ int main(int argc, char **argv)
|
||||
|
||||
const char internal_url[] =
|
||||
"data:text/html,<body style='background:rgb(3,5,7)'><div id='box'></div></body>";
|
||||
const char transparent_css[] = "html,body{margin:0}"
|
||||
"#box{position:fixed;inset:16px;background:rgba(255,0,0,.5)}";
|
||||
const char transparent_css[] =
|
||||
"html,body{margin:0}"
|
||||
"#box{position:fixed;left:16px;top:16px;width:16px;height:16px;"
|
||||
"background:rgb(241,23,17)}"
|
||||
"#box:after{content:'';position:fixed;left:32px;top:32px;width:16px;"
|
||||
"height:16px;background:rgba(255,0,0,.5)}";
|
||||
const char opaque_css[] = "html,body{margin:0;background:rgb(7,19,31)!important}"
|
||||
"#box{position:fixed;left:16px;top:16px;width:32px;height:32px;"
|
||||
"background:rgb(241,23,17);transform:translateZ(0);filter:blur(.1px)}";
|
||||
@@ -136,6 +140,7 @@ int main(int argc, char **argv)
|
||||
write_exact(control[0], css, strlen(css));
|
||||
uint8_t last_bgra[4] = {0};
|
||||
uint8_t last_corner_bgra[4] = {0};
|
||||
uint8_t last_half_bgra[4] = {0};
|
||||
bool found_red = false;
|
||||
int max_attempts = external_url ? 120 : 60;
|
||||
for (int attempt = 0; sent && attempt < max_attempts; attempt++) {
|
||||
@@ -168,10 +173,15 @@ int main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
size_t center = zoom ? ((size_t)5 * width + 15) * 4
|
||||
: ((size_t)(height / 2) * width + width / 2) * 4;
|
||||
: opaque ? ((size_t)(height / 2) * width + width / 2) * 4
|
||||
: ((size_t)24 * width + 24) * 4;
|
||||
memcpy(last_bgra, frame + center, sizeof(last_bgra));
|
||||
size_t corner = zoom ? ((size_t)5 * width + 25) * 4 : 0;
|
||||
memcpy(last_corner_bgra, frame + corner, sizeof(last_corner_bgra));
|
||||
if (!zoom && !opaque) {
|
||||
size_t half = ((size_t)40 * width + 40) * 4;
|
||||
memcpy(last_half_bgra, frame + half, sizeof(last_half_bgra));
|
||||
}
|
||||
bool expected = zoom
|
||||
? last_bgra[0] < 32 && last_bgra[1] < 40 && last_bgra[2] > 210 &&
|
||||
last_bgra[3] == 255 && last_corner_bgra[0] > 20 &&
|
||||
@@ -180,8 +190,10 @@ int main(int argc, char **argv)
|
||||
: opaque
|
||||
? last_bgra[0] < 32 && last_bgra[1] < 40 && last_bgra[2] > 210 &&
|
||||
last_bgra[3] == 255
|
||||
: last_bgra[0] < 8 && last_bgra[1] < 8 && last_bgra[2] > 248 &&
|
||||
last_bgra[3] > 120 && last_bgra[3] < 136 &&
|
||||
: last_bgra[0] < 32 && last_bgra[1] < 40 && last_bgra[2] > 225 &&
|
||||
last_bgra[3] == 255 && last_half_bgra[0] < 8 &&
|
||||
last_half_bgra[1] < 8 && last_half_bgra[2] > 248 &&
|
||||
last_half_bgra[3] > 120 && last_half_bgra[3] < 136 &&
|
||||
last_corner_bgra[0] == 0 && last_corner_bgra[1] == 0 &&
|
||||
last_corner_bgra[2] == 0 && last_corner_bgra[3] == 0;
|
||||
if (expected) {
|
||||
@@ -207,10 +219,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
fprintf(stderr,
|
||||
"renderer did not produce the expected %s red BGRA frame "
|
||||
"(center BGRA=%u,%u,%u,%u; corner BGRA=%u,%u,%u,%u)\n",
|
||||
"(center BGRA=%u,%u,%u,%u; half BGRA=%u,%u,%u,%u; "
|
||||
"corner BGRA=%u,%u,%u,%u)\n",
|
||||
zoom ? "200%-zoomed" : opaque ? "opaque" : "transparent",
|
||||
last_bgra[0], last_bgra[1],
|
||||
last_bgra[2], last_bgra[3], last_corner_bgra[0], last_corner_bgra[1],
|
||||
last_bgra[2], last_bgra[3], last_half_bgra[0], last_half_bgra[1],
|
||||
last_half_bgra[2], last_half_bgra[3], last_corner_bgra[0], last_corner_bgra[1],
|
||||
last_corner_bgra[2], last_corner_bgra[3]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user