From eae559b4c9c7975244c2b4e493611209c4abbec7 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sun, 1 May 2022 19:41:46 +1000 Subject: [PATCH] [client/obs] update to support downscaled frames coming from the host --- client/include/interface/renderer.h | 8 +++-- client/renderers/EGL/desktop.c | 8 ++--- client/renderers/EGL/egl.c | 46 ++++++++++++++------------ client/renderers/OpenGL/opengl.c | 36 +++++++++++---------- client/src/main.c | 28 ++++++++-------- obs/lg.c | 50 ++++++++++++++++++----------- 6 files changed, 99 insertions(+), 77 deletions(-) diff --git a/client/include/interface/renderer.h b/client/include/interface/renderer.h index b92610ab..7fc11d65 100644 --- a/client/include/interface/renderer.h +++ b/client/include/interface/renderer.h @@ -66,9 +66,11 @@ LG_RendererRotate; typedef struct LG_RendererFormat { - FrameType type; // frame type - unsigned int width; // image width - unsigned int height; // image height + FrameType type; // frame type + unsigned int screenWidth; // actual width of the host + 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 pitch; // scanline bytes (or compressed size) unsigned int bpp; // bits per pixel (zero if compressed) diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index b50425fe..f93406a6 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -280,14 +280,14 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format) return false; } - desktop->width = format.width; - desktop->height = format.height; + desktop->width = format.frameWidth; + desktop->height = format.frameHeight; if (!egl_textureSetup( desktop->texture, pixFmt, - format.width, - format.height, + format.frameWidth, + format.frameHeight, format.pitch )) { diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index 845126ea..87336e63 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -340,18 +340,18 @@ static void egl_calc_mouse_size(struct Inst * this) { case LG_ROTATE_0: case LG_ROTATE_180: - this->mouseScaleX = 2.0f / this->format.width; - this->mouseScaleY = 2.0f / this->format.height; - w = this->format.width; - h = this->format.height; + this->mouseScaleX = 2.0f / this->format.screenWidth; + this->mouseScaleY = 2.0f / this->format.screenHeight; + w = this->format.screenWidth; + h = this->format.screenHeight; break; case LG_ROTATE_90: case LG_ROTATE_270: - this->mouseScaleX = 2.0f / this->format.height; - this->mouseScaleY = 2.0f / this->format.width; - w = this->format.height; - h = this->format.width; + this->mouseScaleX = 2.0f / this->format.screenHeight; + this->mouseScaleY = 2.0f / this->format.screenWidth; + w = this->format.screenHeight; + h = this->format.screenWidth; break; default: @@ -419,14 +419,14 @@ static void egl_update_scale_type(struct Inst * this) { case LG_ROTATE_0: case LG_ROTATE_180: - width = this->format.width; - height = this->format.height; + width = this->format.frameWidth; + height = this->format.frameHeight; break; case LG_ROTATE_90: case LG_ROTATE_270: - width = this->format.height; - height = this->format.width; + width = this->format.frameHeight; + height = this->format.frameWidth; break; } @@ -482,8 +482,10 @@ static void egl_onResize(LG_Renderer * renderer, const int width, const int heig { float scale = max(1.0f, this->formatValid ? - max((float)this->format.width / this->width, (float)this->format.height / this->height) - : 1.0f); + max( + (float)this->format.screenWidth / this->width, + (float)this->format.screenHeight / this->height) + : 1.0f); egl_cursorSetScale(this->cursor, scale); } @@ -561,12 +563,12 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo 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_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 */ 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; accumulated->rects[accumulated->count++] = (struct FrameDamageRect) { .x = x, .y = y, - .width = min(this->format.width - x, rect->width + 2), - .height = min(this->format.height - y, rect->height + 2), + .width = min(this->format.frameWidth - x, rect->width + 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) { 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->width, this->height); @@ -1076,7 +1079,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, for (int j = 0; j < count; ++j) accumulated->count += egl_screenToDesktop( 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 { 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->width, this->height); diff --git a/client/renderers/OpenGL/opengl.c b/client/renderers/OpenGL/opengl.c index 9927d7d2..b8366bb0 100644 --- a/client/renderers/OpenGL/opengl.c +++ b/client/renderers/OpenGL/opengl.c @@ -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); glScalef( - (float)this->destRect.w / (float)this->format.width, - (float)this->destRect.h / (float)this->format.height, + (float)this->destRect.w / (float)this->format.frameWidth, + (float)this->destRect.h / (float)this->format.frameHeight, 1.0f ); } @@ -738,7 +738,7 @@ static enum ConfigStatus configure(struct Inst * this) } // 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; g_gl_dynProcs.glGenBuffers(BUFFER_COUNT, this->vboID); @@ -835,8 +835,8 @@ static enum ConfigStatus configure(struct Inst * this) GL_TEXTURE_2D, 0, this->intFormat, - this->format.width, - this->format.height, + this->format.frameWidth, + this->format.frameHeight, 0, this->vboFormat, this->dataFormat, @@ -859,10 +859,11 @@ static enum ConfigStatus configure(struct Inst * this) glBindTexture(GL_TEXTURE_2D, this->frames[i]); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_TRIANGLE_STRIP); - glTexCoord2f(0.0f, 0.0f); glVertex2i(0 , 0 ); - glTexCoord2f(1.0f, 0.0f); glVertex2i(this->format.width, 0 ); - glTexCoord2f(0.0f, 1.0f); glVertex2i(0 , this->format.height); - glTexCoord2f(1.0f, 1.0f); glVertex2i(this->format.width, this->format.height); + glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0); + glTexCoord2f(1.0f, 0.0f); glVertex2i(this->format.frameWidth, 0); + glTexCoord2f(0.0f, 1.0f); glVertex2i(0, this->format.frameHeight); + glTexCoord2f(1.0f, 1.0f); + glVertex2i(this->format.frameWidth, this->format.frameHeight); glEnd(); glBindTexture(GL_TEXTURE_2D, 0); glEndList(); @@ -1119,14 +1120,14 @@ static bool drawFrame(struct Inst * this) const int bpp = this->format.bpp / 8; glPixelStorei(GL_UNPACK_ALIGNMENT , bpp); - glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.width); + glPixelStorei(GL_UNPACK_ROW_LENGTH, this->format.frameWidth); this->texPos = 0; framebuffer_read_fn( this->frame, - this->format.height, - this->format.width, + this->format.frameHeight, + this->format.frameWidth, bpp, this->format.pitch, opengl_bufferFn, @@ -1141,8 +1142,8 @@ static bool drawFrame(struct Inst * this) 0, 0, 0, - this->format.width , - this->format.height, + this->format.frameWidth , + this->format.frameHeight, this->vboFormat, this->dataFormat, (void*)0 @@ -1150,7 +1151,8 @@ static bool drawFrame(struct Inst * this) if (check_gl_error("glTexSubImage2D")) { 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); const bool mipmap = this->opt.mipmap && ( - (this->format.width > this->destRect.w) || - (this->format.height > this->destRect.h)); + (this->format.frameWidth > this->destRect.w) || + (this->format.frameHeight > this->destRect.h)); if (mipmap) { diff --git a/client/src/main.c b/client/src/main.c index 92e912b3..4d8d8ea4 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -611,16 +611,18 @@ int main_frameThread(void * unused) if (!g_state.formatValid || frame->formatVer != formatVer) { // setup the renderer format with the frame format details - lgrFormat.type = frame->type; - lgrFormat.width = frame->width; - lgrFormat.height = frame->height; - lgrFormat.stride = frame->stride; - lgrFormat.pitch = frame->pitch; + lgrFormat.type = frame->type; + lgrFormat.screenWidth = frame->screenWidth; + lgrFormat.screenHeight = frame->screenHeight; + lgrFormat.frameWidth = frame->frameWidth; + lgrFormat.frameHeight = frame->frameHeight; + lgrFormat.stride = frame->stride; + lgrFormat.pitch = frame->pitch; - if (frame->height != frame->realHeight) + if (frame->flags && FRAME_FLAG_TRUNCATED) { 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))); DEBUG_BREAK(); @@ -655,12 +657,12 @@ int main_frameThread(void * unused) case FRAME_TYPE_RGBA: case FRAME_TYPE_BGRA: case FRAME_TYPE_RGBA10: - dataSize = lgrFormat.height * lgrFormat.pitch; + dataSize = lgrFormat.frameHeight * lgrFormat.pitch; lgrFormat.bpp = 32; break; case FRAME_TYPE_RGBA16F: - dataSize = lgrFormat.height * lgrFormat.pitch; + dataSize = lgrFormat.frameHeight * lgrFormat.pitch; lgrFormat.bpp = 64; break; @@ -682,7 +684,7 @@ int main_frameThread(void * unused) DEBUG_INFO("Format: %s %ux%u stride:%u pitch:%u rotation:%d", FrameTypeStr[frame->type], - frame->width, frame->height, + frame->frameWidth, frame->frameHeight, frame->stride, frame->pitch, frame->rotation); @@ -696,11 +698,11 @@ int main_frameThread(void * unused) } LG_UNLOCK(g_state.lgrLock); - g_state.srcSize.x = lgrFormat.width; - g_state.srcSize.y = lgrFormat.height; + g_state.srcSize.x = lgrFormat.screenWidth; + g_state.srcSize.y = lgrFormat.screenHeight; g_state.haveSrcSize = true; if (g_params.autoResize) - g_state.ds->setWindowSize(lgrFormat.width, lgrFormat.height); + g_state.ds->setWindowSize(lgrFormat.frameWidth, lgrFormat.frameHeight); core_updatePositionInfo(); } diff --git a/obs/lg.c b/obs/lg.c index f497bff9..5307348d 100644 --- a/obs/lg.c +++ b/obs/lg.c @@ -72,7 +72,9 @@ typedef struct LGState state; char * shmFile; uint32_t formatVer; - uint32_t width, height; + uint32_t screenWidth, screenHeight; + uint32_t frameWidth, frameHeight; + struct vec2 screenScale; FrameType type; int bpp; struct IVSHMEM shmDev; @@ -574,10 +576,15 @@ static void lgVideoTick(void * data, float seconds) KVMFRFrame * frame = (KVMFRFrame *)msg.mem; if (!this->texture || this->formatVer != frame->formatVer) { - this->formatVer = frame->formatVer; - this->width = frame->width; - this->height = frame->height; - this->type = frame->type; + this->formatVer = frame->formatVer; + this->screenWidth = frame->screenWidth; + this->screenHeight = frame->screenHeight; + this->frameWidth = frame->frameWidth; + this->frameHeight = frame->frameHeight; + this->type = frame->type; + + this->screenScale.x = this->screenWidth / this->frameWidth ; + this->screenScale.y = this->screenHeight / this->frameHeight; obs_enter_graphics(); if (this->texture) @@ -626,12 +633,14 @@ static void lgVideoTick(void * data, float seconds) #if LIBOBS_API_MAJOR_VER >= 27 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) 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 }, &(uint32_t) { 0 }, &(uint64_t) { 0 }); @@ -652,7 +661,7 @@ static void lgVideoTick(void * data, float seconds) if (!this->texture) 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) { @@ -671,12 +680,12 @@ static void lgVideoTick(void * data, float seconds) FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset); framebuffer_read( fb, - this->texData, // dst - this->linesize, // dstpitch - frame->height, // height - frame->width, // width - this->bpp, // bpp - frame->pitch // linepitch + this->texData, // dst + this->linesize, // dstpitch + frame->frameHeight, // height + frame->frameWidth, // width + this->bpp, // bpp + frame->pitch // linepitch ); lgmpClientMessageDone(this->frameQueue); @@ -716,8 +725,8 @@ static void lgVideoRender(void * data, gs_effect_t * effect) { .x = m4.t.x, .y = m4.t.y, - .cx = (double)this->width * m4.x.x, - .cy = (double)this->height * m4.y.y + .cx = (double)this->frameWidth * m4.x.x, + .cy = (double)this->frameHeight * m4.y.y }; 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_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) { @@ -765,13 +777,13 @@ static void lgVideoRender(void * data, gs_effect_t * effect) static uint32_t lgGetWidth(void * data) { LGPlugin * this = (LGPlugin *)data; - return this->width; + return this->frameWidth; } static uint32_t lgGetHeight(void * data) { LGPlugin * this = (LGPlugin *)data; - return this->height; + return this->frameHeight; } struct obs_source_info lg_source =