diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index 73d1eea4..e7608d2f 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -28,6 +28,7 @@ #include "app.h" #include "texture.h" +#include "texture_buffer.h" #include "shader.h" #include "desktop_rects.h" #include "cimgui.h" @@ -705,26 +706,9 @@ void egl_desktopSwSurfaceDrawFill(EGL_Desktop * desktop, height = (bottom > desktop->swSurfaceHeight ? desktop->swSurfaceHeight : (int)bottom) - y; - /* This is a fairly hacky way to update a software surface, but it preserves - * the existing incremental fill behavior. */ - - uint32_t * line = malloc((size_t)width * sizeof(*line)); - if (!line) - { - DEBUG_ERROR("Failed to allocate software surface fill row"); - return; - } - - for(int i = 0; i < width; ++i) - line[i] = color; - - for(int dy = 0; dy < height; ++dy) - egl_textureUpdateRect(desktop->swSurfaceTexture, - x, y + dy, width, 1, width, width * sizeof(*line), - (uint8_t *)line, false); - - free(line); - atomic_store(&desktop->processFrame, true); + if (egl_texBufferStreamFill( + desktop->swSurfaceTexture, x, y, width, height, color)) + atomic_store(&desktop->processFrame, true); } void egl_desktopSwSurfaceDrawBitmap(EGL_Desktop * desktop, diff --git a/client/renderers/EGL/texture_buffer.c b/client/renderers/EGL/texture_buffer.c index 91d8a04e..e86ca6ae 100644 --- a/client/renderers/EGL/texture_buffer.c +++ b/client/renderers/EGL/texture_buffer.c @@ -390,6 +390,44 @@ static bool egl_texBufferStreamUpdate(EGL_Texture * texture, return true; } +bool egl_texBufferStreamFill(EGL_Texture * texture, + int x, int y, int width, int height, uint32_t color) +{ + TextureBuffer * this = UPCAST(TextureBuffer, texture); + + DEBUG_ASSERT(texture->format.bpp == sizeof(color)); + if (texture->format.bpp != sizeof(color)) + return false; + + if (!egl_texBufferStreamLock(this)) + return false; + + uint8_t * row = this->buf[this->bufIndex].map + + texture->format.pitch * y + x * texture->format.bpp; + for (int dy = 0; dy < height; ++dy) + { + uint32_t * dst = (uint32_t *)row; + for (int dx = 0; dx < width; ++dx) + dst[dx] = color; + row += texture->format.pitch; + } + + const EGL_TexUpdate update = + { + .x = x, + .y = y, + .width = width, + .height = height, + }; + + this->slotToken[this->bufIndex] = LG_RENDERER_FRAME_TOKEN_NONE; + this->buf[this->bufIndex].updated = true; + egl_texBufferDamageAdd(this, this->bufIndex, &update); + LG_UNLOCK(this->copyLock); + + return true; +} + EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture, LG_RendererFrameToken frameTokenLimit) { diff --git a/client/renderers/EGL/texture_buffer.h b/client/renderers/EGL/texture_buffer.h index 68eaf316..789994b6 100644 --- a/client/renderers/EGL/texture_buffer.h +++ b/client/renderers/EGL/texture_buffer.h @@ -70,6 +70,8 @@ bool egl_texBufferStreamSetup(EGL_Texture * texture_, const EGL_TexSetup * setup); /* Returns with copyLock held when the current upload buffer is safe to write. */ bool egl_texBufferStreamLock(TextureBuffer * texture); +bool egl_texBufferStreamFill(EGL_Texture * texture, + int x, int y, int width, int height, uint32_t color); EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture_, LG_RendererFrameToken frameTokenLimit); EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture_, GLuint * tex, diff --git a/client/tests/spice_test.c b/client/tests/spice_test.c index a6065783..c2420016 100644 --- a/client/tests/spice_test.c +++ b/client/tests/spice_test.c @@ -721,11 +721,11 @@ static void testSurfaceEvents(void) CHECK(f.log.configN == 1); CHECK(f.log.width == 2); CHECK(f.log.height == 1); - CHECK(f.log.fillN == 1); + CHECK(f.log.fillN == 0); spiceSurface_drawFill( f.transport.surface, 0, 1, 2, 3, 4, 0xaabbccdd); - CHECK(f.log.fillN == 2); + CHECK(f.log.fillN == 1); CHECK(f.log.x == 1); CHECK(f.log.y == 2); CHECK(f.log.w == 3); @@ -776,7 +776,7 @@ static void testSurfaceEvents(void) spiceSurface_destroy(f.transport.surface, 0); CHECK(f.log.destroyN == 1); spiceSurface_drawFill(f.transport.surface, 0, 0, 0, 1, 1, 0); - CHECK(f.log.fillN == 2); + CHECK(f.log.fillN == 1); sw->detach(&f.transport); freeFixture(&f); } @@ -844,9 +844,9 @@ static void testSurfaceDetach(void) CHECK(pthread_join(detachThread, NULL) == 0); CHECK(atomic_load(&detach.done)); CHECK(f.log.configN == 1); - CHECK(f.log.fillN == 1); + CHECK(f.log.fillN == 0); spiceSurface_drawFill(f.transport.surface, 0, 0, 0, 1, 1, 0); - CHECK(f.log.fillN == 1); + CHECK(f.log.fillN == 0); freeFixture(&f); } diff --git a/client/transports/SPICE/surface.c b/client/transports/SPICE/surface.c index a234ed09..d6fa029e 100644 --- a/client/transports/SPICE/surface.c +++ b/client/transports/SPICE/surface.c @@ -199,11 +199,7 @@ void spiceSurface_create(SpiceSurface * surface, unsigned int surfaceId, LG_LOCK_SHARED(surface->eventsLock); if (surface->events) - { surface->events->configure(surface->eventOpaque, width, height); - surface->events->drawFill( - surface->eventOpaque, 0, 0, width, height, 0); - } LG_UNLOCK_SHARED(surface->eventsLock); }