mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 06:47:19 +00:00
[client] egl: add spice display support
This commit is contained in:
parent
faae785c44
commit
6cbfa6e734
@ -42,7 +42,8 @@
|
|||||||
|
|
||||||
#define FPS_TEXTURE 0
|
#define FPS_TEXTURE 0
|
||||||
#define MOUSE_TEXTURE 1
|
#define MOUSE_TEXTURE 1
|
||||||
#define TEXTURE_COUNT 2
|
#define SPICE_TEXTURE 2
|
||||||
|
#define TEXTURE_COUNT 3
|
||||||
|
|
||||||
#define FADE_TIME 1000000
|
#define FADE_TIME 1000000
|
||||||
|
|
||||||
@ -136,13 +137,17 @@ struct Inst
|
|||||||
int texWIndex, texRIndex;
|
int texWIndex, texRIndex;
|
||||||
int texList;
|
int texList;
|
||||||
int mouseList;
|
int mouseList;
|
||||||
|
int spiceList;
|
||||||
LG_RendererRect destRect;
|
LG_RendererRect destRect;
|
||||||
|
struct IntPoint spiceSize;
|
||||||
|
bool spiceShow;
|
||||||
|
|
||||||
bool hasTextures, hasFrames;
|
bool hasTextures, hasFrames;
|
||||||
GLuint frames[BUFFER_COUNT];
|
GLuint frames[BUFFER_COUNT];
|
||||||
GLsync fences[BUFFER_COUNT];
|
GLsync fences[BUFFER_COUNT];
|
||||||
GLuint textures[TEXTURE_COUNT];
|
GLuint textures[TEXTURE_COUNT];
|
||||||
|
|
||||||
|
bool start;
|
||||||
bool waiting;
|
bool waiting;
|
||||||
uint64_t waitFadeTime;
|
uint64_t waitFadeTime;
|
||||||
bool waitDone;
|
bool waitDone;
|
||||||
@ -174,7 +179,7 @@ enum ConfigStatus
|
|||||||
|
|
||||||
static void deconfigure(struct Inst * this);
|
static void deconfigure(struct Inst * this);
|
||||||
static enum ConfigStatus configure(struct Inst * this);
|
static enum ConfigStatus configure(struct Inst * this);
|
||||||
static void updateMouseShape(struct Inst * this, bool * newShape);
|
static void updateMouseShape(struct Inst * this);
|
||||||
static bool drawFrame(struct Inst * this);
|
static bool drawFrame(struct Inst * this);
|
||||||
static void drawMouse(struct Inst * this);
|
static void drawMouse(struct Inst * this);
|
||||||
static void renderWait(struct Inst * this);
|
static void renderWait(struct Inst * this);
|
||||||
@ -207,7 +212,6 @@ bool opengl_create(LG_Renderer ** renderer, const LG_RendererParams params,
|
|||||||
this->opt.preventBuffer = option_get_bool("opengl", "preventBuffer");
|
this->opt.preventBuffer = option_get_bool("opengl", "preventBuffer");
|
||||||
this->opt.amdPinnedMem = option_get_bool("opengl", "amdPinnedMem" );
|
this->opt.amdPinnedMem = option_get_bool("opengl", "amdPinnedMem" );
|
||||||
|
|
||||||
|
|
||||||
LG_LOCK_INIT(this->formatLock);
|
LG_LOCK_INIT(this->formatLock);
|
||||||
LG_LOCK_INIT(this->frameLock );
|
LG_LOCK_INIT(this->frameLock );
|
||||||
LG_LOCK_INIT(this->mouseLock );
|
LG_LOCK_INIT(this->mouseLock );
|
||||||
@ -235,6 +239,7 @@ void opengl_deinitialize(LG_Renderer * renderer)
|
|||||||
|
|
||||||
glDeleteLists(this->texList , BUFFER_COUNT);
|
glDeleteLists(this->texList , BUFFER_COUNT);
|
||||||
glDeleteLists(this->mouseList, 1);
|
glDeleteLists(this->mouseList, 1);
|
||||||
|
glDeleteLists(this->spiceList, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
deconfigure(this);
|
deconfigure(this);
|
||||||
@ -266,6 +271,34 @@ void opengl_onRestart(LG_Renderer * renderer)
|
|||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
|
||||||
this->waiting = true;
|
this->waiting = true;
|
||||||
|
this->start = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupModelView(struct Inst * this)
|
||||||
|
{
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
if (!this->destRect.valid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int fw, fh;
|
||||||
|
if (this->spiceShow)
|
||||||
|
{
|
||||||
|
fw = this->spiceSize.x;
|
||||||
|
fh = this->spiceSize.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fw = this->format.frameWidth;
|
||||||
|
fh = this->format.frameHeight;
|
||||||
|
}
|
||||||
|
glTranslatef(this->destRect.x, this->destRect.y, 0.0f);
|
||||||
|
glScalef(
|
||||||
|
(float)this->destRect.w / (float)fw,
|
||||||
|
(float)this->destRect.h / (float)fh,
|
||||||
|
1.0f
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void opengl_onResize(LG_Renderer * renderer, const int width, const int height, const double scale,
|
void opengl_onResize(LG_Renderer * renderer, const int width, const int height, const double scale,
|
||||||
@ -292,19 +325,6 @@ void opengl_onResize(LG_Renderer * renderer, const int width, const int height,
|
|||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glOrtho(0, this->window.x, this->window.y, 0, -1, 1);
|
glOrtho(0, this->window.x, this->window.y, 0, -1, 1);
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
if (this->destRect.valid)
|
|
||||||
{
|
|
||||||
glTranslatef(this->destRect.x, this->destRect.y, 0.0f);
|
|
||||||
glScalef(
|
|
||||||
(float)this->destRect.w / (float)this->format.frameWidth,
|
|
||||||
(float)this->destRect.h / (float)this->format.frameHeight,
|
|
||||||
1.0f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is needed to refresh the font atlas texture
|
// this is needed to refresh the font atlas texture
|
||||||
ImGui_ImplOpenGL2_Shutdown();
|
ImGui_ImplOpenGL2_Shutdown();
|
||||||
ImGui_ImplOpenGL2_Init();
|
ImGui_ImplOpenGL2_Init();
|
||||||
@ -381,18 +401,7 @@ bool opengl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame, int dmaFd
|
|||||||
atomic_store_explicit(&this->frameUpdate, true, memory_order_release);
|
atomic_store_explicit(&this->frameUpdate, true, memory_order_release);
|
||||||
LG_UNLOCK(this->frameLock);
|
LG_UNLOCK(this->frameLock);
|
||||||
|
|
||||||
if (this->waiting)
|
this->start = true;
|
||||||
{
|
|
||||||
this->waiting = false;
|
|
||||||
if (!this->params.quickSplash)
|
|
||||||
this->waitFadeTime = microtime() + FADE_TIME;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glDisable(GL_MULTISAMPLE);
|
|
||||||
this->waitDone = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,6 +465,7 @@ bool opengl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
|||||||
// generate lists for drawing
|
// generate lists for drawing
|
||||||
this->texList = glGenLists(BUFFER_COUNT);
|
this->texList = glGenLists(BUFFER_COUNT);
|
||||||
this->mouseList = glGenLists(1);
|
this->mouseList = glGenLists(1);
|
||||||
|
this->spiceList = glGenLists(1);
|
||||||
|
|
||||||
// create the overlay textures
|
// create the overlay textures
|
||||||
glGenTextures(TEXTURE_COUNT, this->textures);
|
glGenTextures(TEXTURE_COUNT, this->textures);
|
||||||
@ -489,6 +499,20 @@ bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate, const bool
|
|||||||
{
|
{
|
||||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
|
||||||
|
setupModelView(this);
|
||||||
|
|
||||||
|
if (this->start && this->waiting)
|
||||||
|
{
|
||||||
|
this->waiting = false;
|
||||||
|
if (!this->params.quickSplash)
|
||||||
|
this->waitFadeTime = microtime() + FADE_TIME;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glDisable(GL_MULTISAMPLE);
|
||||||
|
this->waitDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch(configure(this))
|
switch(configure(this))
|
||||||
{
|
{
|
||||||
case CONFIG_STATUS_ERROR:
|
case CONFIG_STATUS_ERROR:
|
||||||
@ -508,10 +532,14 @@ bool opengl_render(LG_Renderer * renderer, LG_RendererRotate rotate, const bool
|
|||||||
renderWait(this);
|
renderWait(this);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool newShape;
|
if (this->spiceShow)
|
||||||
updateMouseShape(this, &newShape);
|
glCallList(this->spiceList);
|
||||||
glCallList(this->texList + this->texRIndex);
|
else
|
||||||
drawMouse(this);
|
{
|
||||||
|
updateMouseShape(this);
|
||||||
|
glCallList(this->texList + this->texRIndex);
|
||||||
|
drawMouse(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->waitDone)
|
if (!this->waitDone)
|
||||||
renderWait(this);
|
renderWait(this);
|
||||||
@ -569,6 +597,9 @@ static void renderWait(struct Inst * this)
|
|||||||
a = 1.0f;
|
a = 1.0f;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (this->waitDone)
|
||||||
|
return;
|
||||||
|
|
||||||
uint64_t t = microtime();
|
uint64_t t = microtime();
|
||||||
if (t > this->waitFadeTime)
|
if (t > this->waitFadeTime)
|
||||||
{
|
{
|
||||||
@ -626,12 +657,129 @@ static void renderWait(struct Inst * this)
|
|||||||
drawTorusArc(-14, 83, 5, 7, 10, M_PI , M_PI / 2.0f);
|
drawTorusArc(-14, 83, 5, 7, 10, M_PI , M_PI / 2.0f);
|
||||||
drawTorusArc( 14, 83, 5, 7, 10, M_PI * 1.5f, M_PI / 2.0f);
|
drawTorusArc( 14, 83, 5, 7, 10, M_PI * 1.5f, M_PI / 2.0f);
|
||||||
|
|
||||||
//FIXME: draw the diagnoal marks on the circle
|
//FIXME: draw the diagonal marks on the circle
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void opengl_spiceConfigure(LG_Renderer * renderer, int width, int height)
|
||||||
|
{
|
||||||
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
this->spiceSize.x = width;
|
||||||
|
this->spiceSize.y = height;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
||||||
|
glTexImage2D
|
||||||
|
(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0 ,
|
||||||
|
GL_RGBA,
|
||||||
|
width ,
|
||||||
|
height ,
|
||||||
|
0 ,
|
||||||
|
GL_BGRA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
// create the display lists
|
||||||
|
glNewList(this->spiceList, GL_COMPILE);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
||||||
|
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->spiceSize.x, 0);
|
||||||
|
glTexCoord2f(0.0f, 1.0f); glVertex2i(0, this->spiceSize.y);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex2i(this->spiceSize.x, this->spiceSize.y);
|
||||||
|
glEnd();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void opengl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width,
|
||||||
|
int height, uint32_t color)
|
||||||
|
{
|
||||||
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
|
||||||
|
/* this is a fairly hacky way to do this, but since it's only for the fallback
|
||||||
|
* spice display it's not really an issue */
|
||||||
|
|
||||||
|
uint32_t line[width];
|
||||||
|
for(int x = 0; x < width; ++x)
|
||||||
|
line[x] = color;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||||
|
for(; y < height; ++y)
|
||||||
|
glTexSubImage2D
|
||||||
|
(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0 ,
|
||||||
|
x ,
|
||||||
|
y ,
|
||||||
|
width ,
|
||||||
|
1 ,
|
||||||
|
GL_BGRA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
line
|
||||||
|
);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void opengl_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);
|
||||||
|
|
||||||
|
if (!topDown)
|
||||||
|
{
|
||||||
|
// this is non-optimal but as spice is a fallback it's not too critical
|
||||||
|
uint8_t line[stride];
|
||||||
|
for(int y = 0; y < height / 2; ++y)
|
||||||
|
{
|
||||||
|
uint8_t * top = data + y * stride;
|
||||||
|
uint8_t * btm = data + (height - y - 1) * stride;
|
||||||
|
memcpy(line, top , stride);
|
||||||
|
memcpy(top , btm , stride);
|
||||||
|
memcpy(btm , line, stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->textures[SPICE_TEXTURE]);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / 4);
|
||||||
|
glTexSubImage2D
|
||||||
|
(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0 ,
|
||||||
|
x ,
|
||||||
|
y ,
|
||||||
|
width ,
|
||||||
|
height ,
|
||||||
|
GL_BGRA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
data
|
||||||
|
);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void opengl_spiceShow(LG_Renderer * renderer, bool show)
|
||||||
|
{
|
||||||
|
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||||
|
this->spiceShow = show;
|
||||||
|
if (show)
|
||||||
|
this->start = true;
|
||||||
|
}
|
||||||
|
|
||||||
const LG_RendererOps LGR_OpenGL =
|
const LG_RendererOps LGR_OpenGL =
|
||||||
{
|
{
|
||||||
.getName = opengl_getName,
|
.getName = opengl_getName,
|
||||||
@ -648,7 +796,12 @@ const LG_RendererOps LGR_OpenGL =
|
|||||||
.onFrame = opengl_onFrame,
|
.onFrame = opengl_onFrame,
|
||||||
.renderStartup = opengl_renderStartup,
|
.renderStartup = opengl_renderStartup,
|
||||||
.needsRender = opengl_needsRender,
|
.needsRender = opengl_needsRender,
|
||||||
.render = opengl_render
|
.render = opengl_render,
|
||||||
|
|
||||||
|
.spiceConfigure = opengl_spiceConfigure,
|
||||||
|
.spiceDrawFill = opengl_spiceDrawFill,
|
||||||
|
.spiceDrawBitmap = opengl_spiceDrawBitmap,
|
||||||
|
.spiceShow = opengl_spiceShow
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool _checkGLError(unsigned int line, const char * name)
|
static bool _checkGLError(unsigned int line, const char * name)
|
||||||
@ -915,10 +1068,9 @@ static void deconfigure(struct Inst * this)
|
|||||||
this->configured = false;
|
this->configured = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void updateMouseShape(struct Inst * this, bool * newShape)
|
static void updateMouseShape(struct Inst * this)
|
||||||
{
|
{
|
||||||
LG_LOCK(this->mouseLock);
|
LG_LOCK(this->mouseLock);
|
||||||
*newShape = this->newShape;
|
|
||||||
if (!this->newShape)
|
if (!this->newShape)
|
||||||
{
|
{
|
||||||
LG_UNLOCK(this->mouseLock);
|
LG_UNLOCK(this->mouseLock);
|
||||||
|
Loading…
Reference in New Issue
Block a user