From 247e867f188bc6901500d966f46d285b30b98c7b Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sun, 22 May 2022 18:19:58 +1000 Subject: [PATCH] [client] egl: implemented SPICE display support --- client/include/interface/renderer.h | 2 +- client/renderers/EGL/cursor.c | 10 +-- client/renderers/EGL/desktop.c | 85 +++++++++++++++++++--- client/renderers/EGL/desktop.h | 7 ++ client/renderers/EGL/egl.c | 49 +++++++++++-- client/renderers/EGL/egltypes.h | 2 + client/renderers/EGL/framebuffer.c | 2 +- client/renderers/EGL/texture.c | 67 +++++++++-------- client/renderers/EGL/texture.h | 23 ++++-- client/renderers/EGL/texture_buffer.c | 52 +++++++++++-- client/renderers/EGL/texture_buffer.h | 6 +- client/renderers/EGL/texture_dmabuf.c | 5 +- client/renderers/EGL/texture_framebuffer.c | 5 +- client/renderers/EGL/texture_util.h | 2 +- client/src/main.c | 18 ++++- client/src/render_queue.c | 21 ++++-- client/src/render_queue.h | 3 +- 17 files changed, 273 insertions(+), 86 deletions(-) diff --git a/client/include/interface/renderer.h b/client/include/interface/renderer.h index 75320095..98d422e1 100644 --- a/client/include/interface/renderer.h +++ b/client/include/interface/renderer.h @@ -181,7 +181,7 @@ typedef struct LG_RendererOps /* draw an image on the spice display, data is RGBA32 */ void (*spiceDrawBitmap)(LG_Renderer * renderer, int x, int y, int width, - int height, int stride, uint8_t * data); + int height, int stride, uint8_t * data, bool topDown); /* show the spice display */ void (*spiceShow)(LG_Renderer * renderer, bool show); diff --git a/client/renderers/EGL/cursor.c b/client/renderers/EGL/cursor.c index 5387dd9a..4228697f 100644 --- a/client/renderers/EGL/cursor.c +++ b/client/renderers/EGL/cursor.c @@ -87,7 +87,7 @@ static bool cursorTexInit(struct CursorTex * t, const char * vertex_code , size_t vertex_size, const char * fragment_code, size_t fragment_size) { - if (!egl_textureInit(&t->texture, NULL, EGL_TEXTYPE_BUFFER, false)) + if (!egl_textureInit(&t->texture, NULL, EGL_TEXTYPE_BUFFER)) { DEBUG_ERROR("Failed to initialize the cursor texture"); return false; @@ -278,7 +278,7 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor, egl_textureSetup(cursor->mono.texture, EGL_PF_BGRA, cursor->width, cursor->height, sizeof(xor[0])); - egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor); + egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor, true); } // fall through @@ -286,7 +286,7 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor, { egl_textureSetup(cursor->norm.texture, EGL_PF_BGRA, cursor->width, cursor->height, cursor->stride); - egl_textureUpdate(cursor->norm.texture, data); + egl_textureUpdate(cursor->norm.texture, data, true); break; } @@ -314,8 +314,8 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor, cursor->width, cursor->height, sizeof(and[0])); egl_textureSetup(cursor->mono.texture, EGL_PF_BGRA, cursor->width, cursor->height, sizeof(xor[0])); - egl_textureUpdate(cursor->norm.texture, (uint8_t *)and); - egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor); + egl_textureUpdate(cursor->norm.texture, (uint8_t *)and, true); + egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor, true); break; } } diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index f93406a6..224a4310 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -65,6 +65,10 @@ struct EGL_Desktop int width, height; LG_RendererRotate rotate; + bool useSpice; + int spiceWidth, spiceHeight; + EGL_Texture * spiceTexture; + // scale algorithm int scaleAlgo; @@ -125,7 +129,7 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display, desktop->display = display; if (!egl_textureInit(&desktop->texture, display, - useDMA ? EGL_TEXTYPE_DMABUF : EGL_TEXTYPE_FRAMEBUFFER, true)) + useDMA ? EGL_TEXTYPE_DMABUF : EGL_TEXTYPE_FRAMEBUFFER)) { DEBUG_ERROR("Failed to initialize the desktop texture"); return false; @@ -202,6 +206,7 @@ void egl_desktopFree(EGL_Desktop ** desktop) return; egl_textureFree (&(*desktop)->texture ); + egl_textureFree (&(*desktop)->spiceTexture ); egl_shaderFree (&(*desktop)->shader.shader); egl_desktopRectsFree(&(*desktop)->mesh ); countedBufferRelease(&(*desktop)->matrix ); @@ -329,7 +334,7 @@ bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dma egl_textureFree(&desktop->texture); if (!egl_textureInit(&desktop->texture, desktop->display, - EGL_TEXTYPE_FRAMEBUFFER, true)) + EGL_TEXTYPE_FRAMEBUFFER)) { DEBUG_ERROR("Failed to initialize the desktop texture"); return false; @@ -359,11 +364,27 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType, LG_RendererRotate rotate, const struct DamageRects * rects) { + EGL_Texture * tex; + int width, height; + + if (desktop->useSpice) + { + tex = desktop->spiceTexture; + width = desktop->spiceWidth; + height = desktop->spiceHeight; + } + else + { + tex = desktop->texture; + width = desktop->width; + height = desktop->height; + } + if (outputWidth == 0 && outputHeight == 0) DEBUG_FATAL("outputWidth || outputHeight == 0"); enum EGL_TexStatus status; - if ((status = egl_textureProcess(desktop->texture)) != EGL_TEX_STATUS_OK) + if ((status = egl_textureProcess(tex)) != EGL_TEX_STATUS_OK) { if (status != EGL_TEX_STATUS_NOTREADY) DEBUG_ERROR("Failed to process the desktop texture"); @@ -372,13 +393,13 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, int scaleAlgo = EGL_SCALE_NEAREST; egl_desktopRectsMatrix((float *)desktop->matrix->data, - desktop->width, desktop->height, x, y, scaleX, scaleY, rotate); - egl_desktopRectsUpdate(desktop->mesh, rects, desktop->width, desktop->height); + width, height, x, y, scaleX, scaleY, rotate); + egl_desktopRectsUpdate(desktop->mesh, rects, width, height); if (atomic_exchange(&desktop->processFrame, false) || egl_postProcessConfigModified(desktop->pp)) - egl_postProcessRun(desktop->pp, desktop->texture, desktop->mesh, - desktop->width, desktop->height, outputWidth, outputHeight); + egl_postProcessRun(desktop->pp, tex, desktop->mesh, + width, height, outputWidth, outputHeight); unsigned int finalSizeX, finalSizeY; GLuint texture = egl_postProcessGetOutput(desktop->pp, @@ -389,9 +410,9 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); - glBindSampler(0, desktop->texture->sampler); + glBindSampler(0, tex->sampler); - if (finalSizeX > desktop->width || finalSizeY > desktop->height) + if (finalSizeX > width || finalSizeY > height) scaleType = EGL_DESKTOP_DOWNSCALE; switch (desktop->scaleAlgo) @@ -425,7 +446,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, { .type = EGL_UNIFORM_TYPE_2F, .location = shader->uDesktopSize, - .f = { desktop->width, desktop->height }, + .f = { width, height }, }, { .type = EGL_UNIFORM_TYPE_M3x2FV, @@ -451,3 +472,47 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, glBindTexture(GL_TEXTURE_2D, 0); return true; } + +void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height) +{ + if (!desktop->spiceTexture) + if (!egl_textureInit(&desktop->spiceTexture, desktop->display, + EGL_TEXTYPE_BUFFER_MAP)) + { + DEBUG_ERROR("Failed to initialize the spice desktop texture"); + return; + } + + if (!egl_textureSetup( + desktop->spiceTexture, + EGL_PF_BGRA, + width, + height, + width * 4 + )) + { + DEBUG_ERROR("Failed to setup the spice desktop texture"); + return; + } + + desktop->spiceWidth = width; + desktop->spiceHeight = height; +} + +void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width, + int height, uint32_t color) +{ +} + +void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width, + int height, int stride, uint8_t * data, bool topDown) +{ + egl_textureUpdateRect(desktop->spiceTexture, + x, y, width, height, stride, data, topDown); + atomic_store(&desktop->processFrame, true); +} + +void egl_desktopSpiceShow(EGL_Desktop * desktop, bool show) +{ + desktop->useSpice = show; +} diff --git a/client/renderers/EGL/desktop.h b/client/renderers/EGL/desktop.h index d43225d3..1589d715 100644 --- a/client/renderers/EGL/desktop.h +++ b/client/renderers/EGL/desktop.h @@ -50,3 +50,10 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth, unsigned int outputHeight, const float x, const float y, const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType, LG_RendererRotate rotate, const struct DamageRects * rects); + +void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height); +void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width, + int height, uint32_t color); +void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width, + int height, int stride, uint8_t * data, bool topDown); +void egl_desktopSpiceShow(EGL_Desktop * desktop, bool show); diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index 87336e63..f2b3ac3f 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -123,6 +123,8 @@ struct Inst RingBuffer importTimings; GraphHandle importGraph; + + bool showSpice; }; static struct Option egl_options[] = @@ -1012,7 +1014,8 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, struct Inst * this = UPCAST(struct Inst, renderer); EGLint bufferAge = egl_bufferAge(this); bool renderAll = invalidateWindow || !this->start || this->hadOverlay || - bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE; + bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE || + this->showSpice; bool hasOverlay = false; struct CursorState cursorState = { .visible = false }; @@ -1103,9 +1106,10 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, this->waitDone = true; } - cursorState = egl_cursorRender(this->cursor, - (this->format.rotate + rotate) % LG_ROTATE_MAX, - this->width, this->height); + if (!this->showSpice) + cursorState = egl_cursorRender(this->cursor, + (this->format.rotate + rotate) % LG_ROTATE_MAX, + this->width, this->height); } else hasOverlay = true; @@ -1207,6 +1211,36 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate, return true; } +static void egl_spiceConfigure(LG_Renderer * renderer, int width, int height) +{ + struct Inst * this = UPCAST(struct Inst, renderer); + egl_desktopSpiceConfigure(this->desktop, width, height); +} + +static void egl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width, + int height, uint32_t color) +{ + struct Inst * this = UPCAST(struct Inst, renderer); + egl_desktopSpiceDrawFill(this->desktop, x, y, width, height, color); +} + +static void egl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int width, + int height, int stride, uint8_t * data, bool topDown) +{ + struct Inst * this = UPCAST(struct Inst, renderer); + egl_desktopSpiceDrawBitmap(this->desktop, x, y, width, height, stride, + data, topDown); +} + +static void egl_spiceShow(LG_Renderer * renderer, bool show) +{ + struct Inst * this = UPCAST(struct Inst, renderer); + this->showSpice = show; + egl_desktopSpiceShow(this->desktop, show); + if (show) + this->start = true; +} + struct LG_RendererOps LGR_EGL = { .getName = egl_getName, @@ -1223,5 +1257,10 @@ struct LG_RendererOps LGR_EGL = .onFrame = egl_onFrame, .renderStartup = egl_renderStartup, .needsRender = egl_needsRender, - .render = egl_render + .render = egl_render, + + .spiceConfigure = egl_spiceConfigure, + .spiceDrawFill = egl_spiceDrawFill, + .spiceDrawBitmap = egl_spiceDrawBitmap, + .spiceShow = egl_spiceShow }; diff --git a/client/renderers/EGL/egltypes.h b/client/renderers/EGL/egltypes.h index 4a57f685..b4f4cc2a 100644 --- a/client/renderers/EGL/egltypes.h +++ b/client/renderers/EGL/egltypes.h @@ -25,6 +25,8 @@ typedef enum EGL_TexType { EGL_TEXTYPE_BUFFER, + EGL_TEXTYPE_BUFFER_MAP, + EGL_TEXTYPE_BUFFER_STREAM, EGL_TEXTYPE_FRAMEBUFFER, EGL_TEXTYPE_DMABUF } diff --git a/client/renderers/EGL/framebuffer.c b/client/renderers/EGL/framebuffer.c index 4df80049..0ad54159 100644 --- a/client/renderers/EGL/framebuffer.c +++ b/client/renderers/EGL/framebuffer.c @@ -40,7 +40,7 @@ bool egl_framebufferInit(EGL_Framebuffer ** fb) return false; } - if (!egl_textureInit(&this->tex, NULL, EGL_TEXTYPE_BUFFER, false)) + if (!egl_textureInit(&this->tex, NULL, EGL_TEXTYPE_BUFFER)) { DEBUG_ERROR("Failed to initialize the texture"); return false; diff --git a/client/renderers/EGL/texture.c b/client/renderers/EGL/texture.c index 3ce135b7..b1f2fbf7 100644 --- a/client/renderers/EGL/texture.c +++ b/client/renderers/EGL/texture.c @@ -37,23 +37,26 @@ extern const EGL_TextureOps EGL_TextureFrameBuffer; extern const EGL_TextureOps EGL_TextureDMABUF; bool egl_textureInit(EGL_Texture ** texture_, EGLDisplay * display, - EGL_TexType type, bool streaming) + EGL_TexType type) { const EGL_TextureOps * ops; switch(type) { case EGL_TEXTYPE_BUFFER: - ops = streaming ? &EGL_TextureBufferStream : &EGL_TextureBuffer; + ops = &EGL_TextureBuffer; + break; + + case EGL_TEXTYPE_BUFFER_MAP: + case EGL_TEXTYPE_BUFFER_STREAM: + ops = &EGL_TextureBufferStream; break; case EGL_TEXTYPE_FRAMEBUFFER: - DEBUG_ASSERT(streaming); ops = &EGL_TextureFrameBuffer; break; case EGL_TEXTYPE_DMABUF: - DEBUG_ASSERT(streaming); ops = &EGL_TextureDMABUF; break; @@ -62,7 +65,7 @@ bool egl_textureInit(EGL_Texture ** texture_, EGLDisplay * display, } *texture_ = NULL; - if (!ops->init(texture_, display)) + if (!ops->init(texture_, type, display)) return false; EGL_Texture * this = *texture_; @@ -105,18 +108,19 @@ bool egl_textureSetup(EGL_Texture * this, enum EGL_PixelFormat pixFmt, return this->ops.setup(this, &setup); } -bool egl_textureUpdate(EGL_Texture * this, const uint8_t * buffer) +bool egl_textureUpdate(EGL_Texture * this, const uint8_t * buffer, bool topDown) { const struct EGL_TexUpdate update = { - .type = EGL_TEXTYPE_BUFFER, - .x = 0, - .y = 0, - .width = this->format.width, - .height = this->format.height, - .pitch = this->format.pitch, - .stride = this->format.stride, - .buffer = buffer + .type = EGL_TEXTYPE_BUFFER, + .x = 0, + .y = 0, + .width = this->format.width, + .height = this->format.height, + .pitch = this->format.pitch, + .stride = this->format.stride, + .topDown = topDown, + .buffer = buffer }; return this->ops.update(this, &update); @@ -124,7 +128,7 @@ bool egl_textureUpdate(EGL_Texture * this, const uint8_t * buffer) bool egl_textureUpdateRect(EGL_Texture * this, int x, int y, int width, int height, int stride, - const uint8_t * buffer) + const uint8_t * buffer, bool topDown) { x = clamp(x , 0, this->format.width ); y = clamp(y , 0, this->format.height ); @@ -136,14 +140,15 @@ bool egl_textureUpdateRect(EGL_Texture * this, const struct EGL_TexUpdate update = { - .type = EGL_TEXTYPE_BUFFER, - .x = x, - .y = y, - .width = width, - .height = height, - .pitch = stride / (stride / width), - .stride = stride, - .buffer = buffer + .type = EGL_TEXTYPE_BUFFER, + .x = x, + .y = y, + .width = width, + .height = height, + .pitch = stride / this->format.bpp, + .stride = stride, + .topDown = topDown, + .buffer = buffer }; return this->ops.update(this, &update); @@ -175,14 +180,14 @@ bool egl_textureUpdateFromDMA(EGL_Texture * this, { const struct EGL_TexUpdate update = { - .type = EGL_TEXTYPE_DMABUF, - .x = 0, - .y = 0, - .width = this->format.width, - .height = this->format.height, - .pitch = this->format.pitch, - .stride = this->format.stride, - .dmaFD = dmaFd + .type = EGL_TEXTYPE_DMABUF, + .x = 0, + .y = 0, + .width = this->format.width, + .height = this->format.height, + .pitch = this->format.pitch, + .stride = this->format.stride, + .dmaFD = dmaFd }; /* wait for completion */ diff --git a/client/renderers/EGL/texture.h b/client/renderers/EGL/texture.h index 3f251a84..43cb20f8 100644 --- a/client/renderers/EGL/texture.h +++ b/client/renderers/EGL/texture.h @@ -50,10 +50,15 @@ typedef struct EGL_TexUpdate union { - /* EGL_TEXTURE_BUFFER */ - const uint8_t * buffer; + /* EGL_TEXTYPE_BUFFER */ + struct + { + // true if row 0 is the top of the image + bool topDown; + const uint8_t * buffer; + }; - /* EGL_TEXTURE_FRAMEBUFFER */ + /* EGL_TEXTYPE_FRAMEBUFFER */ struct { const FrameBuffer * frame; @@ -61,7 +66,7 @@ typedef struct EGL_TexUpdate int rectCount; }; - /* EGL_TEXTURE_DMABUF */ + /* EGL_TEXTYPE_DMABUF */ int dmaFD; }; } @@ -72,7 +77,7 @@ typedef struct EGL_Texture EGL_Texture; typedef struct EGL_TextureOps { /* allocate & initialize an EGL_Texture */ - bool (*init)(EGL_Texture ** texture, EGLDisplay * display); + bool (*init)(EGL_Texture ** texture, EGL_TexType type, EGLDisplay * display); /* free the EGL_Texture */ void (*free)(EGL_Texture * texture); @@ -94,23 +99,25 @@ EGL_TextureOps; struct EGL_Texture { struct EGL_TextureOps ops; + EGL_TexType type; GLuint sampler; EGL_TexFormat format; }; bool egl_textureInit(EGL_Texture ** texture, EGLDisplay * display, - EGL_TexType type, bool streaming); + EGL_TexType type); void egl_textureFree(EGL_Texture ** tex); bool egl_textureSetup(EGL_Texture * texture, enum EGL_PixelFormat pixFmt, size_t width, size_t height, size_t stride); -bool egl_textureUpdate(EGL_Texture * texture, const uint8_t * buffer); +bool egl_textureUpdate(EGL_Texture * texture, const uint8_t * buffer, + bool topDown); bool egl_textureUpdateRect(EGL_Texture * texture, int x, int y, int width, int height, int stride, - const uint8_t * buffer); + const uint8_t * buffer, bool topDown); bool egl_textureUpdateFromFrame(EGL_Texture * texture, const FrameBuffer * frame, const FrameDamageRect * damageRects, diff --git a/client/renderers/EGL/texture_buffer.c b/client/renderers/EGL/texture_buffer.c index 5f7b497b..cd596d10 100644 --- a/client/renderers/EGL/texture_buffer.c +++ b/client/renderers/EGL/texture_buffer.c @@ -46,7 +46,8 @@ static void egl_texBuffer_cleanup(TextureBuffer * this) // common functions -bool egl_texBufferInit(EGL_Texture ** texture, EGLDisplay * display) +bool egl_texBufferInit(EGL_Texture ** texture, EGL_TexType type, + EGLDisplay * display) { TextureBuffer * this; if (!*texture) @@ -140,14 +141,29 @@ EGL_TexStatus egl_texBufferGet(EGL_Texture * texture, GLuint * tex) // streaming functions -bool egl_texBufferStreamInit(EGL_Texture ** texture, EGLDisplay * display) +bool egl_texBufferStreamInit(EGL_Texture ** texture, EGL_TexType type, + EGLDisplay * display) { - if (!egl_texBufferInit(texture, display)) + if (!egl_texBufferInit(texture, type, display)) return false; TextureBuffer * this = UPCAST(TextureBuffer, *texture); - this->texCount = 2; + switch(type) + { + case EGL_TEXTYPE_BUFFER_STREAM: + case EGL_TEXTYPE_DMABUF: + this->texCount = 2; + break; + + case EGL_TEXTYPE_BUFFER_MAP: + this->texCount = 1; + break; + + default: + DEBUG_UNREACHABLE(); + } + LG_LOCK_INIT(this->copyLock); return true; } @@ -168,8 +184,32 @@ static bool egl_texBufferStreamUpdate(EGL_Texture * texture, DEBUG_ASSERT(update->type == EGL_TEXTYPE_BUFFER); LG_LOCK(this->copyLock); - memcpy(this->buf[this->bufIndex].map, update->buffer, - texture->format.bufferSize); + + uint8_t * dst = this->buf[this->bufIndex].map + + texture->format.stride * update->y + + update->x * texture->format.bpp; + + if (update->topDown) + { + const uint8_t * src = update->buffer; + for(int y = 0; y < update->height; ++y) + { + memcpy(dst, src, update->stride); + dst += texture->format.stride; + src += update->stride; + } + } + else + { + const uint8_t * src = update->buffer + update->stride * update->height; + for(int y = 0; y < update->height; ++y) + { + src -= update->stride; + memcpy(dst, src, update->stride); + dst += texture->format.stride; + } + } + this->buf[this->bufIndex].updated = true; LG_UNLOCK(this->copyLock); diff --git a/client/renderers/EGL/texture_buffer.h b/client/renderers/EGL/texture_buffer.h index 351caa2e..4b364126 100644 --- a/client/renderers/EGL/texture_buffer.h +++ b/client/renderers/EGL/texture_buffer.h @@ -42,13 +42,15 @@ typedef struct TextureBuffer } TextureBuffer; -bool egl_texBufferInit(EGL_Texture ** texture_, EGLDisplay * display); +bool egl_texBufferInit(EGL_Texture ** texture_, EGL_TexType type, + EGLDisplay * display); void egl_texBufferFree(EGL_Texture * texture_); bool egl_texBufferSetup(EGL_Texture * texture_, const EGL_TexSetup * setup); EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture_); EGL_TexStatus egl_texBufferGet(EGL_Texture * texture_, GLuint * tex); -bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGLDisplay * display); +bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type, + EGLDisplay * display); bool egl_texBufferStreamSetup(EGL_Texture * texture_, const EGL_TexSetup * setup); EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture_); diff --git a/client/renderers/EGL/texture_dmabuf.c b/client/renderers/EGL/texture_dmabuf.c index 98c27283..c701f822 100644 --- a/client/renderers/EGL/texture_dmabuf.c +++ b/client/renderers/EGL/texture_dmabuf.c @@ -54,7 +54,8 @@ static void egl_texDMABUFCleanup(TexDMABUF * this) // dmabuf functions -static bool egl_texDMABUFInit(EGL_Texture ** texture, EGLDisplay * display) +static bool egl_texDMABUFInit(EGL_Texture ** texture, EGL_TexType type, + EGLDisplay * display) { TexDMABUF * this = calloc(1, sizeof(*this)); *texture = &this->base.base; @@ -67,7 +68,7 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGLDisplay * display) } EGL_Texture * parent = &this->base.base; - if (!egl_texBufferStreamInit(&parent, display)) + if (!egl_texBufferStreamInit(&parent, type, display)) { vector_destroy(&this->images); free(this); diff --git a/client/renderers/EGL/texture_framebuffer.c b/client/renderers/EGL/texture_framebuffer.c index 788e87fa..9d1d656f 100644 --- a/client/renderers/EGL/texture_framebuffer.c +++ b/client/renderers/EGL/texture_framebuffer.c @@ -38,13 +38,14 @@ typedef struct TexFB } TexFB; -static bool egl_texFBInit(EGL_Texture ** texture, EGLDisplay * display) +static bool egl_texFBInit(EGL_Texture ** texture, EGL_TexType type, + EGLDisplay * display) { TexFB * this = calloc(1, sizeof(*this)); *texture = &this->base.base; EGL_Texture * parent = &this->base.base; - if (!egl_texBufferStreamInit(&parent, display)) + if (!egl_texBufferStreamInit(&parent, type, display)) { free(this); *texture = NULL; diff --git a/client/renderers/EGL/texture_util.h b/client/renderers/EGL/texture_util.h index 809accc7..a0d7c1c0 100644 --- a/client/renderers/EGL/texture_util.h +++ b/client/renderers/EGL/texture_util.h @@ -35,7 +35,7 @@ typedef struct EGL_TexFormat unsigned int fourcc; size_t bufferSize; - size_t width, height; + size_t width , height; size_t stride, pitch; } EGL_TexFormat; diff --git a/client/src/main.c b/client/src/main.c index 301139c7..41482d28 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -50,6 +50,7 @@ #include "common/version.h" #include "common/paths.h" #include "common/cpuinfo.h" +#include "common/ll.h" #include "core.h" #include "app.h" @@ -809,7 +810,9 @@ int main_frameThread(void * unused) lgmpClientUnsubscribe(&queue); RENDERER(onRestart); - app_useSpiceDisplay(true); + + if (g_state.state != APP_STATE_SHUTDOWN) + app_useSpiceDisplay(true); if (g_state.useDMA) { @@ -873,6 +876,14 @@ void spiceReady(void) static void spice_surfaceCreate(unsigned int surfaceId, PSSurfaceFormat format, unsigned int width, unsigned int height) { + DEBUG_INFO("Create SPICE surface: id: %d, size: %dx%d", + surfaceId, width, height); + + g_state.srcSize.x = width; + g_state.srcSize.y = height; + g_state.haveSrcSize = true; + core_updatePositionInfo(); + renderQueue_spiceConfigure(width, height); if (g_state.lgr) RENDERER(spiceShow, true); @@ -880,6 +891,7 @@ static void spice_surfaceCreate(unsigned int surfaceId, PSSurfaceFormat format, static void spice_surfaceDestroy(unsigned int surfaceId) { + DEBUG_INFO("Destroy spice surface %d", surfaceId); if (g_state.lgr) RENDERER(spiceShow, false); } @@ -893,7 +905,7 @@ static void spice_drawFill(unsigned int surfaceId, int x, int y, int width, static void spice_drawBitmap(unsigned int surfaceId, PSBitmapFormat format, bool topDown, int x, int y, int width, int height, int stride, void * data) { - renderQueue_spiceDrawBitmap(x, y, width, height, stride, data); + renderQueue_spiceDrawBitmap(x, y, width, height, stride, data, topDown); } int spiceThread(void * arg) @@ -1579,8 +1591,8 @@ restart: { if (!lgmpClientSessionValid(g_state.lgmp)) { - g_state.state = APP_STATE_RESTART; DEBUG_INFO("Waiting for the host to restart..."); + g_state.state = APP_STATE_RESTART; break; } g_state.ds->wait(100); diff --git a/client/src/render_queue.c b/client/src/render_queue.c index 8edf4d14..102f3b76 100644 --- a/client/src/render_queue.c +++ b/client/src/render_queue.c @@ -32,6 +32,15 @@ void renderQueue_init(void) l_renderQueue = ll_new(); } +void renderQueue_free(void) +{ + if (!l_renderQueue) + return; + + renderQueue_clear(); + ll_free(l_renderQueue); +} + void renderQueue_clear(void) { RenderCommand * cmd; @@ -68,7 +77,7 @@ void renderQueue_spiceDrawFill(int x, int y, int width, int height, } void renderQueue_spiceDrawBitmap(int x, int y, int width, int height, int stride, - void * data) + void * data, bool topDown) { RenderCommand * cmd = malloc(sizeof(*cmd)); cmd->op = SPICE_OP_DRAW_BITMAP; @@ -78,17 +87,12 @@ void renderQueue_spiceDrawBitmap(int x, int y, int width, int height, int stride cmd->drawBitmap.height = height; cmd->drawBitmap.stride = stride; cmd->drawBitmap.data = malloc(height * stride); + cmd->drawBitmap.topDown = topDown; memcpy(cmd->drawBitmap.data, data, height * stride); ll_push(l_renderQueue, cmd); app_invalidateWindow(true); } -void renderQueue_free(void) -{ - renderQueue_clear(); - ll_free(l_renderQueue); -} - void renderQueue_process(void) { RenderCommand * cmd; @@ -112,7 +116,8 @@ void renderQueue_process(void) RENDERER(spiceDrawBitmap, cmd->drawBitmap.x , cmd->drawBitmap.y, cmd->drawBitmap.width , cmd->drawBitmap.height, - cmd->drawBitmap.stride, cmd->drawBitmap.data); + cmd->drawBitmap.stride, cmd->drawBitmap.data, + cmd->drawBitmap.topDown); free(cmd->drawBitmap.data); break; } diff --git a/client/src/render_queue.h b/client/src/render_queue.h index d86545f5..ac675ea6 100644 --- a/client/src/render_queue.h +++ b/client/src/render_queue.h @@ -52,6 +52,7 @@ typedef struct int width, height; int stride; uint8_t * data; + bool topDown; } drawBitmap; }; @@ -69,4 +70,4 @@ void renderQueue_spiceDrawFill(int x, int y, int width, int height, uint32_t color); void renderQueue_spiceDrawBitmap(int x, int y, int width, int height, int stride, - void * data); + void * data, bool topDown);