mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-12-22 13:33:40 +00:00
[client] egl: implemented SPICE display support
This commit is contained in:
parent
6699018ed1
commit
247e867f18
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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_);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user