[client/obs] update to support downscaled frames coming from the host

This commit is contained in:
Geoffrey McRae 2022-05-01 19:41:46 +10:00
parent 3134ec84de
commit eae559b4c9
6 changed files with 99 additions and 77 deletions

View File

@ -67,8 +67,10 @@ LG_RendererRotate;
typedef struct LG_RendererFormat typedef struct LG_RendererFormat
{ {
FrameType type; // frame type FrameType type; // frame type
unsigned int width; // image width unsigned int screenWidth; // actual width of the host
unsigned int height; // image height unsigned int screenHeight; // actual height of the host
unsigned int frameWidth; // width of frame transmitted
unsigned int frameHeight; // height of frame transmitted
unsigned int stride; // scanline width (zero if compresed) unsigned int stride; // scanline width (zero if compresed)
unsigned int pitch; // scanline bytes (or compressed size) unsigned int pitch; // scanline bytes (or compressed size)
unsigned int bpp; // bits per pixel (zero if compressed) unsigned int bpp; // bits per pixel (zero if compressed)

View File

@ -280,14 +280,14 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format)
return false; return false;
} }
desktop->width = format.width; desktop->width = format.frameWidth;
desktop->height = format.height; desktop->height = format.frameHeight;
if (!egl_textureSetup( if (!egl_textureSetup(
desktop->texture, desktop->texture,
pixFmt, pixFmt,
format.width, format.frameWidth,
format.height, format.frameHeight,
format.pitch format.pitch
)) ))
{ {

View File

@ -340,18 +340,18 @@ static void egl_calc_mouse_size(struct Inst * this)
{ {
case LG_ROTATE_0: case LG_ROTATE_0:
case LG_ROTATE_180: case LG_ROTATE_180:
this->mouseScaleX = 2.0f / this->format.width; this->mouseScaleX = 2.0f / this->format.screenWidth;
this->mouseScaleY = 2.0f / this->format.height; this->mouseScaleY = 2.0f / this->format.screenHeight;
w = this->format.width; w = this->format.screenWidth;
h = this->format.height; h = this->format.screenHeight;
break; break;
case LG_ROTATE_90: case LG_ROTATE_90:
case LG_ROTATE_270: case LG_ROTATE_270:
this->mouseScaleX = 2.0f / this->format.height; this->mouseScaleX = 2.0f / this->format.screenHeight;
this->mouseScaleY = 2.0f / this->format.width; this->mouseScaleY = 2.0f / this->format.screenWidth;
w = this->format.height; w = this->format.screenHeight;
h = this->format.width; h = this->format.screenWidth;
break; break;
default: default:
@ -419,14 +419,14 @@ static void egl_update_scale_type(struct Inst * this)
{ {
case LG_ROTATE_0: case LG_ROTATE_0:
case LG_ROTATE_180: case LG_ROTATE_180:
width = this->format.width; width = this->format.frameWidth;
height = this->format.height; height = this->format.frameHeight;
break; break;
case LG_ROTATE_90: case LG_ROTATE_90:
case LG_ROTATE_270: case LG_ROTATE_270:
width = this->format.height; width = this->format.frameHeight;
height = this->format.width; height = this->format.frameWidth;
break; break;
} }
@ -482,7 +482,9 @@ static void egl_onResize(LG_Renderer * renderer, const int width, const int heig
{ {
float scale = max(1.0f, float scale = max(1.0f,
this->formatValid ? this->formatValid ?
max((float)this->format.width / this->width, (float)this->format.height / this->height) max(
(float)this->format.screenWidth / this->width,
(float)this->format.screenHeight / this->height)
: 1.0f); : 1.0f);
egl_cursorSetScale(this->cursor, scale); egl_cursorSetScale(this->cursor, scale);
} }
@ -561,12 +563,12 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo
if (this->scalePointer) if (this->scalePointer)
{ {
float scale = max(1.0f, (float)format.width / this->width); float scale = max(1.0f, (float)format.screenWidth / this->width);
egl_cursorSetScale(this->cursor, scale); egl_cursorSetScale(this->cursor, scale);
} }
egl_update_scale_type(this); egl_update_scale_type(this);
egl_damageSetup(this->damage, format.width, format.height); egl_damageSetup(this->damage, format.frameWidth, format.frameHeight);
/* we need full screen damage when the format changes */ /* we need full screen damage when the format changes */
INTERLOCKED_SECTION(this->desktopDamageLock, { INTERLOCKED_SECTION(this->desktopDamageLock, {
@ -1043,8 +1045,8 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
int y = rect->y > 0 ? rect->y - 1 : 0; int y = rect->y > 0 ? rect->y - 1 : 0;
accumulated->rects[accumulated->count++] = (struct FrameDamageRect) { accumulated->rects[accumulated->count++] = (struct FrameDamageRect) {
.x = x, .y = y, .x = x, .y = y,
.width = min(this->format.width - x, rect->width + 2), .width = min(this->format.frameWidth - x, rect->width + 2),
.height = min(this->format.height - y, rect->height + 2), .height = min(this->format.frameHeight - y, rect->height + 2),
}; };
} }
} }
@ -1057,7 +1059,8 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
if (!renderAll) if (!renderAll)
{ {
double matrix[6]; double matrix[6];
egl_screenToDesktopMatrix(matrix, this->format.width, this->format.height, egl_screenToDesktopMatrix(matrix,
this->format.frameWidth, this->format.frameHeight,
this->translateX, this->translateY, this->scaleX, this->scaleY, rotate, this->translateX, this->translateY, this->scaleX, this->scaleY, rotate,
this->width, this->height); this->width, this->height);
@ -1076,7 +1079,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
for (int j = 0; j < count; ++j) for (int j = 0; j < count; ++j)
accumulated->count += egl_screenToDesktop( accumulated->count += egl_screenToDesktop(
accumulated->rects + accumulated->count, matrix, damage + j, accumulated->rects + accumulated->count, matrix, damage + j,
this->format.width, this->format.height this->format.frameWidth, this->format.frameHeight
); );
} }
@ -1184,7 +1187,8 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
else else
{ {
double matrix[6]; double matrix[6];
egl_desktopToScreenMatrix(matrix, this->format.width, this->format.height, egl_desktopToScreenMatrix(matrix,
this->format.frameWidth, this->format.frameHeight,
this->translateX, this->translateY, this->scaleX, this->scaleY, rotate, this->translateX, this->translateY, this->scaleX, this->scaleY, rotate,
this->width, this->height); this->width, this->height);

View File

@ -299,8 +299,8 @@ void opengl_onResize(LG_Renderer * renderer, const int width, const int height,
{ {
glTranslatef(this->destRect.x, this->destRect.y, 0.0f); glTranslatef(this->destRect.x, this->destRect.y, 0.0f);
glScalef( glScalef(
(float)this->destRect.w / (float)this->format.width, (float)this->destRect.w / (float)this->format.frameWidth,
(float)this->destRect.h / (float)this->format.height, (float)this->destRect.h / (float)this->format.frameHeight,
1.0f 1.0f
); );
} }
@ -738,7 +738,7 @@ static enum ConfigStatus configure(struct Inst * this)
} }
// calculate the texture size in bytes // calculate the texture size in bytes
this->texSize = this->format.height * this->format.pitch; this->texSize = this->format.frameHeight * this->format.pitch;
this->texPos = 0; this->texPos = 0;
g_gl_dynProcs.glGenBuffers(BUFFER_COUNT, this->vboID); g_gl_dynProcs.glGenBuffers(BUFFER_COUNT, this->vboID);
@ -835,8 +835,8 @@ static enum ConfigStatus configure(struct Inst * this)
GL_TEXTURE_2D, GL_TEXTURE_2D,
0, 0,
this->intFormat, this->intFormat,
this->format.width, this->format.frameWidth,
this->format.height, this->format.frameHeight,
0, 0,
this->vboFormat, this->vboFormat,
this->dataFormat, this->dataFormat,
@ -860,9 +860,10 @@ static enum ConfigStatus configure(struct Inst * this)
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBegin(GL_TRIANGLE_STRIP); glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0); glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0);
glTexCoord2f(1.0f, 0.0f); glVertex2i(this->format.width, 0 ); glTexCoord2f(1.0f, 0.0f); glVertex2i(this->format.frameWidth, 0);
glTexCoord2f(0.0f, 1.0f); glVertex2i(0 , this->format.height); glTexCoord2f(0.0f, 1.0f); glVertex2i(0, this->format.frameHeight);
glTexCoord2f(1.0f, 1.0f); glVertex2i(this->format.width, this->format.height); glTexCoord2f(1.0f, 1.0f);
glVertex2i(this->format.frameWidth, this->format.frameHeight);
glEnd(); glEnd();
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glEndList(); glEndList();
@ -1119,14 +1120,14 @@ static bool drawFrame(struct Inst * this)
const int bpp = this->format.bpp / 8; const int bpp = this->format.bpp / 8;
glPixelStorei(GL_UNPACK_ALIGNMENT , bpp); glPixelStorei(GL_UNPACK_ALIGNMENT , bpp);
glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.width); glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.frameWidth);
this->texPos = 0; this->texPos = 0;
framebuffer_read_fn( framebuffer_read_fn(
this->frame, this->frame,
this->format.height, this->format.frameHeight,
this->format.width, this->format.frameWidth,
bpp, bpp,
this->format.pitch, this->format.pitch,
opengl_bufferFn, opengl_bufferFn,
@ -1141,8 +1142,8 @@ static bool drawFrame(struct Inst * this)
0, 0,
0, 0,
0, 0,
this->format.width , this->format.frameWidth ,
this->format.height, this->format.frameHeight,
this->vboFormat, this->vboFormat,
this->dataFormat, this->dataFormat,
(void*)0 (void*)0
@ -1150,7 +1151,8 @@ static bool drawFrame(struct Inst * this)
if (check_gl_error("glTexSubImage2D")) if (check_gl_error("glTexSubImage2D"))
{ {
DEBUG_ERROR("texWIndex: %u, width: %u, height: %u, vboFormat: %x, texSize: %lu", DEBUG_ERROR("texWIndex: %u, width: %u, height: %u, vboFormat: %x, texSize: %lu",
this->texWIndex, this->format.width, this->format.height, this->vboFormat, this->texSize this->texWIndex, this->format.frameWidth, this->format.frameHeight,
this->vboFormat, this->texSize
); );
} }
@ -1158,8 +1160,8 @@ static bool drawFrame(struct Inst * this)
g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); g_gl_dynProcs.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
const bool mipmap = this->opt.mipmap && ( const bool mipmap = this->opt.mipmap && (
(this->format.width > this->destRect.w) || (this->format.frameWidth > this->destRect.w) ||
(this->format.height > this->destRect.h)); (this->format.frameHeight > this->destRect.h));
if (mipmap) if (mipmap)
{ {

View File

@ -612,15 +612,17 @@ int main_frameThread(void * unused)
{ {
// setup the renderer format with the frame format details // setup the renderer format with the frame format details
lgrFormat.type = frame->type; lgrFormat.type = frame->type;
lgrFormat.width = frame->width; lgrFormat.screenWidth = frame->screenWidth;
lgrFormat.height = frame->height; lgrFormat.screenHeight = frame->screenHeight;
lgrFormat.frameWidth = frame->frameWidth;
lgrFormat.frameHeight = frame->frameHeight;
lgrFormat.stride = frame->stride; lgrFormat.stride = frame->stride;
lgrFormat.pitch = frame->pitch; lgrFormat.pitch = frame->pitch;
if (frame->height != frame->realHeight) if (frame->flags && FRAME_FLAG_TRUNCATED)
{ {
const float needed = const float needed =
((frame->realHeight * frame->pitch * 2) / 1048576.0f) + 10.0f; ((frame->screenHeight * frame->pitch * 2) / 1048576.0f) + 10.0f;
const int size = (int)powf(2.0f, ceilf(logf(needed) / logf(2.0f))); const int size = (int)powf(2.0f, ceilf(logf(needed) / logf(2.0f)));
DEBUG_BREAK(); DEBUG_BREAK();
@ -655,12 +657,12 @@ int main_frameThread(void * unused)
case FRAME_TYPE_RGBA: case FRAME_TYPE_RGBA:
case FRAME_TYPE_BGRA: case FRAME_TYPE_BGRA:
case FRAME_TYPE_RGBA10: case FRAME_TYPE_RGBA10:
dataSize = lgrFormat.height * lgrFormat.pitch; dataSize = lgrFormat.frameHeight * lgrFormat.pitch;
lgrFormat.bpp = 32; lgrFormat.bpp = 32;
break; break;
case FRAME_TYPE_RGBA16F: case FRAME_TYPE_RGBA16F:
dataSize = lgrFormat.height * lgrFormat.pitch; dataSize = lgrFormat.frameHeight * lgrFormat.pitch;
lgrFormat.bpp = 64; lgrFormat.bpp = 64;
break; break;
@ -682,7 +684,7 @@ int main_frameThread(void * unused)
DEBUG_INFO("Format: %s %ux%u stride:%u pitch:%u rotation:%d", DEBUG_INFO("Format: %s %ux%u stride:%u pitch:%u rotation:%d",
FrameTypeStr[frame->type], FrameTypeStr[frame->type],
frame->width, frame->height, frame->frameWidth, frame->frameHeight,
frame->stride, frame->pitch, frame->stride, frame->pitch,
frame->rotation); frame->rotation);
@ -696,11 +698,11 @@ int main_frameThread(void * unused)
} }
LG_UNLOCK(g_state.lgrLock); LG_UNLOCK(g_state.lgrLock);
g_state.srcSize.x = lgrFormat.width; g_state.srcSize.x = lgrFormat.screenWidth;
g_state.srcSize.y = lgrFormat.height; g_state.srcSize.y = lgrFormat.screenHeight;
g_state.haveSrcSize = true; g_state.haveSrcSize = true;
if (g_params.autoResize) if (g_params.autoResize)
g_state.ds->setWindowSize(lgrFormat.width, lgrFormat.height); g_state.ds->setWindowSize(lgrFormat.frameWidth, lgrFormat.frameHeight);
core_updatePositionInfo(); core_updatePositionInfo();
} }

View File

@ -72,7 +72,9 @@ typedef struct
LGState state; LGState state;
char * shmFile; char * shmFile;
uint32_t formatVer; uint32_t formatVer;
uint32_t width, height; uint32_t screenWidth, screenHeight;
uint32_t frameWidth, frameHeight;
struct vec2 screenScale;
FrameType type; FrameType type;
int bpp; int bpp;
struct IVSHMEM shmDev; struct IVSHMEM shmDev;
@ -575,10 +577,15 @@ static void lgVideoTick(void * data, float seconds)
if (!this->texture || this->formatVer != frame->formatVer) if (!this->texture || this->formatVer != frame->formatVer)
{ {
this->formatVer = frame->formatVer; this->formatVer = frame->formatVer;
this->width = frame->width; this->screenWidth = frame->screenWidth;
this->height = frame->height; this->screenHeight = frame->screenHeight;
this->frameWidth = frame->frameWidth;
this->frameHeight = frame->frameHeight;
this->type = frame->type; this->type = frame->type;
this->screenScale.x = this->screenWidth / this->frameWidth ;
this->screenScale.y = this->screenHeight / this->frameHeight;
obs_enter_graphics(); obs_enter_graphics();
if (this->texture) if (this->texture)
{ {
@ -626,12 +633,14 @@ static void lgVideoTick(void * data, float seconds)
#if LIBOBS_API_MAJOR_VER >= 27 #if LIBOBS_API_MAJOR_VER >= 27
if (this->dmabuf) if (this->dmabuf)
{ {
int fd = dmabufGetFd(this, &msg, frame, frame->height * frame->pitch); int fd = dmabufGetFd(this, &msg, frame, frame->frameHeight * frame->pitch);
if (fd < 0) if (fd < 0)
goto dmabuf_fail; goto dmabuf_fail;
this->texture = gs_texture_create_from_dmabuf(frame->width, frame->height, this->texture = gs_texture_create_from_dmabuf(
frame->frameWidth,
frame->frameHeight,
drm_format, format, 1, &fd, &(uint32_t) { frame->pitch }, drm_format, format, 1, &fd, &(uint32_t) { frame->pitch },
&(uint32_t) { 0 }, &(uint64_t) { 0 }); &(uint32_t) { 0 }, &(uint64_t) { 0 });
@ -652,7 +661,7 @@ static void lgVideoTick(void * data, float seconds)
if (!this->texture) if (!this->texture)
this->texture = gs_texture_create( this->texture = gs_texture_create(
this->width, this->height, format, 1, NULL, GS_DYNAMIC); this->frameWidth, this->frameHeight, format, 1, NULL, GS_DYNAMIC);
if (!this->texture) if (!this->texture)
{ {
@ -673,8 +682,8 @@ static void lgVideoTick(void * data, float seconds)
fb, fb,
this->texData, // dst this->texData, // dst
this->linesize, // dstpitch this->linesize, // dstpitch
frame->height, // height frame->frameHeight, // height
frame->width, // width frame->frameWidth, // width
this->bpp, // bpp this->bpp, // bpp
frame->pitch // linepitch frame->pitch // linepitch
); );
@ -716,8 +725,8 @@ static void lgVideoRender(void * data, gs_effect_t * effect)
{ {
.x = m4.t.x, .x = m4.t.x,
.y = m4.t.y, .y = m4.t.y,
.cx = (double)this->width * m4.x.x, .cx = (double)this->frameWidth * m4.x.x,
.cy = (double)this->height * m4.y.y .cy = (double)this->frameHeight * m4.y.y
}; };
gs_set_scissor_rect(&r); gs_set_scissor_rect(&r);
@ -726,7 +735,10 @@ static void lgVideoRender(void * data, gs_effect_t * effect)
gs_effect_set_texture(image, this->cursorTex); gs_effect_set_texture(image, this->cursorTex);
gs_matrix_push(); gs_matrix_push();
gs_matrix_translate3f(this->cursorRect.x, this->cursorRect.y, 0.0f); gs_matrix_translate3f(
this->cursorRect.x / this->screenScale.x,
this->cursorRect.y / this->screenScale.y,
0.0f);
if (!this->cursorMono) if (!this->cursorMono)
{ {
@ -765,13 +777,13 @@ static void lgVideoRender(void * data, gs_effect_t * effect)
static uint32_t lgGetWidth(void * data) static uint32_t lgGetWidth(void * data)
{ {
LGPlugin * this = (LGPlugin *)data; LGPlugin * this = (LGPlugin *)data;
return this->width; return this->frameWidth;
} }
static uint32_t lgGetHeight(void * data) static uint32_t lgGetHeight(void * data)
{ {
LGPlugin * this = (LGPlugin *)data; LGPlugin * this = (LGPlugin *)data;
return this->height; return this->frameHeight;
} }
struct obs_source_info lg_source = struct obs_source_info lg_source =