mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-14 01:58:25 +00:00
[egl] added intial cursor support
This commit is contained in:
parent
c0c63fd93b
commit
d331a3dd5a
@ -19,6 +19,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
|
|
||||||
#include "lg-renderer.h"
|
#include "lg-renderer.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include <SDL2/SDL_syswm.h>
|
#include <SDL2/SDL_syswm.h>
|
||||||
#include <SDL2/SDL_egl.h>
|
#include <SDL2/SDL_egl.h>
|
||||||
@ -40,6 +41,7 @@ static struct Options defaultOptions =
|
|||||||
struct Models
|
struct Models
|
||||||
{
|
{
|
||||||
struct EGL_Model * desktop;
|
struct EGL_Model * desktop;
|
||||||
|
struct EGL_Model * mouse;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Shaders
|
struct Shaders
|
||||||
@ -47,11 +49,15 @@ struct Shaders
|
|||||||
struct EGL_Shader * rgba;
|
struct EGL_Shader * rgba;
|
||||||
struct EGL_Shader * bgra;
|
struct EGL_Shader * bgra;
|
||||||
struct EGL_Shader * yuv;
|
struct EGL_Shader * yuv;
|
||||||
|
|
||||||
|
struct EGL_Shader * mouse_bgra;
|
||||||
|
struct EGL_Shader * mouse_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Textures
|
struct Textures
|
||||||
{
|
{
|
||||||
struct EGL_Texture * desktop;
|
struct EGL_Texture * desktop;
|
||||||
|
struct EGL_Texture * mouse;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Inst
|
struct Inst
|
||||||
@ -77,8 +83,27 @@ struct Inst
|
|||||||
size_t frameSize;
|
size_t frameSize;
|
||||||
const uint8_t * data;
|
const uint8_t * data;
|
||||||
bool update;
|
bool update;
|
||||||
|
int screenW, screenH;
|
||||||
|
|
||||||
|
bool mouseVisible;
|
||||||
|
float mouseX, mouseY, mouseW, mouseH;
|
||||||
|
float mouseScaleX, mouseScaleY;
|
||||||
|
EGL_Shader * mouseShader;
|
||||||
|
GLint mouseUniformLoc;
|
||||||
|
|
||||||
|
LG_Lock mouseLock;
|
||||||
|
LG_RendererCursor mouseCursor;
|
||||||
|
int mouseWidth;
|
||||||
|
int mouseHeight;
|
||||||
|
int mousePitch;
|
||||||
|
uint8_t * mouseData;
|
||||||
|
size_t mouseDataSize;
|
||||||
|
bool mouseUpdate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void update_mouse_shape(struct Inst * this);
|
||||||
|
|
||||||
const char * egl_get_name()
|
const char * egl_get_name()
|
||||||
{
|
{
|
||||||
return "EGL";
|
return "EGL";
|
||||||
@ -100,6 +125,8 @@ bool egl_create(void ** opaque, const LG_RendererParams params)
|
|||||||
memcpy(&this->params, ¶ms , sizeof(LG_RendererParams));
|
memcpy(&this->params, ¶ms , sizeof(LG_RendererParams));
|
||||||
memcpy(&this->opt , &defaultOptions, sizeof(struct Options ));
|
memcpy(&this->opt , &defaultOptions, sizeof(struct Options ));
|
||||||
|
|
||||||
|
LG_LOCK_INIT(this->mouseLock);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,25 +145,72 @@ void egl_deinitialize(void * opaque)
|
|||||||
struct Inst * this = (struct Inst *)opaque;
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
|
||||||
egl_model_free (&this->models .desktop);
|
egl_model_free (&this->models .desktop);
|
||||||
egl_shader_free (&this->shaders .rgba );
|
egl_model_free (&this->models .mouse );
|
||||||
egl_shader_free (&this->shaders .bgra );
|
egl_shader_free (&this->shaders .rgba );
|
||||||
egl_shader_free (&this->shaders .yuv );
|
egl_shader_free (&this->shaders .bgra );
|
||||||
|
egl_shader_free (&this->shaders .yuv );
|
||||||
|
egl_shader_free (&this->shaders .mouse_bgra);
|
||||||
|
egl_shader_free (&this->shaders .mouse_mask);
|
||||||
egl_texture_free(&this->textures.desktop);
|
egl_texture_free(&this->textures.desktop);
|
||||||
|
egl_texture_free(&this->textures.mouse );
|
||||||
|
|
||||||
|
LG_LOCK_FREE(this->mouseLock);
|
||||||
|
if (this->mouseData)
|
||||||
|
free(this->mouseData);
|
||||||
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void egl_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect)
|
void egl_on_resize(void * opaque, const int width, const int height, const LG_RendererRect destRect)
|
||||||
{
|
{
|
||||||
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
|
||||||
|
this->screenW = width;
|
||||||
|
this->screenH = height;
|
||||||
|
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
|
this->mouseScaleX = 2.0f / width ;
|
||||||
|
this->mouseScaleY = 2.0f / height;
|
||||||
|
|
||||||
|
this->mouseW = this->mouseWidth * (1.0f / this->screenW);
|
||||||
|
this->mouseH = this->mouseHeight * (1.0f / this->screenH);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool egl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data)
|
bool egl_on_mouse_shape(void * opaque, const LG_RendererCursor cursor, const int width, const int height, const int pitch, const uint8_t * data)
|
||||||
{
|
{
|
||||||
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
|
||||||
|
LG_LOCK(this->mouseLock);
|
||||||
|
this->mouseCursor = cursor;
|
||||||
|
this->mouseWidth = width;
|
||||||
|
this->mouseHeight = height;
|
||||||
|
this->mousePitch = pitch;
|
||||||
|
|
||||||
|
this->mouseW = this->mouseWidth * (1.0f / this->screenW);
|
||||||
|
this->mouseH = this->mouseHeight * (1.0f / this->screenH);
|
||||||
|
|
||||||
|
const size_t size = height * pitch;
|
||||||
|
if (size > this->mouseDataSize)
|
||||||
|
{
|
||||||
|
if (this->mouseData)
|
||||||
|
free(this->mouseData);
|
||||||
|
this->mouseData = (uint8_t *)malloc(size);
|
||||||
|
this->mouseDataSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(this->mouseData, data, size);
|
||||||
|
this->mouseUpdate = true;
|
||||||
|
LG_UNLOCK(this->mouseLock);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool egl_on_mouse_event(void * opaque, const bool visible , const int x, const int y)
|
bool egl_on_mouse_event(void * opaque, const bool visible , const int x, const int y)
|
||||||
{
|
{
|
||||||
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
this->mouseVisible = visible;
|
||||||
|
this->mouseX = ((float)x * this->mouseScaleX) - 1.0f;
|
||||||
|
this->mouseY = ((float)y * this->mouseScaleY) - 1.0f;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +328,7 @@ bool egl_render_startup(void * opaque, SDL_Window * window)
|
|||||||
DEBUG_INFO("Renderer: %s", glGetString(GL_RENDERER));
|
DEBUG_INFO("Renderer: %s", glGetString(GL_RENDERER));
|
||||||
DEBUG_INFO("Version : %s", glGetString(GL_VERSION ));
|
DEBUG_INFO("Version : %s", glGetString(GL_VERSION ));
|
||||||
|
|
||||||
static const GLfloat desktop[] =
|
static const GLfloat square[] =
|
||||||
{
|
{
|
||||||
-1.0f, -1.0f, 0.0f,
|
-1.0f, -1.0f, 0.0f,
|
||||||
1.0f, -1.0f, 0.0f,
|
1.0f, -1.0f, 0.0f,
|
||||||
@ -270,25 +344,61 @@ bool egl_render_startup(void * opaque, SDL_Window * window)
|
|||||||
1.0f, 0.0f
|
1.0f, 0.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!egl_shader_init(&this->shaders.rgba)) return false;
|
if (!egl_shader_init(&this->shaders.rgba))
|
||||||
if (!egl_shader_init(&this->shaders.bgra)) return false;
|
return false;
|
||||||
if (!egl_shader_init(&this->shaders.yuv )) return false;
|
|
||||||
|
|
||||||
if (!egl_shader_compile(this->shaders.rgba, egl_vertex_shader_basic, sizeof(egl_vertex_shader_basic), egl_fragment_shader_rgba, sizeof(egl_fragment_shader_rgba))) return false;
|
if (!egl_shader_init(&this->shaders.bgra))
|
||||||
if (!egl_shader_compile(this->shaders.bgra, egl_vertex_shader_basic, sizeof(egl_vertex_shader_basic), egl_fragment_shader_bgra, sizeof(egl_fragment_shader_bgra))) return false;
|
return false;
|
||||||
if (!egl_shader_compile(this->shaders.yuv , egl_vertex_shader_basic, sizeof(egl_vertex_shader_basic), egl_fragment_shader_yuv , sizeof(egl_fragment_shader_yuv ))) return false;
|
|
||||||
|
if (!egl_shader_init(&this->shaders.yuv))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!egl_shader_init(&this->shaders.mouse_bgra))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!egl_shader_init(&this->shaders.mouse_mask))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!egl_shader_compile(this->shaders.rgba, egl_vertex_shader_basic, sizeof(egl_vertex_shader_basic), egl_fragment_shader_rgba, sizeof(egl_fragment_shader_rgba)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!egl_shader_compile(this->shaders.bgra, egl_vertex_shader_basic, sizeof(egl_vertex_shader_basic), egl_fragment_shader_bgra, sizeof(egl_fragment_shader_bgra)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!egl_shader_compile(this->shaders.yuv, egl_vertex_shader_basic, sizeof(egl_vertex_shader_basic), egl_fragment_shader_yuv , sizeof(egl_fragment_shader_yuv )))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!egl_shader_compile(this->shaders.mouse_bgra, egl_vertex_shader_mouse, sizeof(egl_vertex_shader_mouse), egl_fragment_shader_bgra, sizeof(egl_fragment_shader_bgra)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!egl_shader_compile(this->shaders.mouse_mask, egl_vertex_shader_mouse, sizeof(egl_vertex_shader_mouse), egl_fragment_shader_mask, sizeof(egl_fragment_shader_mask)))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!egl_texture_init(&this->textures.desktop))
|
if (!egl_texture_init(&this->textures.desktop))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!egl_texture_init(&this->textures.mouse))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!egl_model_init(&this->models.desktop))
|
if (!egl_model_init(&this->models.desktop))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
egl_model_set_verticies(this->models.desktop, desktop, sizeof(desktop) / sizeof(GLfloat));
|
if (!egl_model_init(&this->models.mouse))
|
||||||
egl_model_set_uvs (this->models.desktop, uvs , sizeof(uvs ) / sizeof(GLfloat));
|
return false;
|
||||||
|
|
||||||
|
egl_model_set_verticies(this->models.desktop, square , sizeof(square) / sizeof(GLfloat));
|
||||||
|
egl_model_set_uvs (this->models.desktop, uvs , sizeof(uvs ) / sizeof(GLfloat));
|
||||||
egl_model_set_texture (this->models.desktop, this->textures.desktop);
|
egl_model_set_texture (this->models.desktop, this->textures.desktop);
|
||||||
|
|
||||||
|
egl_model_set_verticies(this->models.mouse, square , sizeof(square) / sizeof(GLfloat));
|
||||||
|
egl_model_set_uvs (this->models.mouse, uvs , sizeof(uvs ) / sizeof(GLfloat));
|
||||||
|
egl_model_set_texture (this->models.mouse, this->textures.mouse);
|
||||||
|
|
||||||
eglSwapInterval(this->display, this->opt.vsync ? 1 : 0);
|
eglSwapInterval(this->display, this->opt.vsync ? 1 : 0);
|
||||||
|
|
||||||
|
glEnable (GL_BLEND);
|
||||||
|
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,33 +411,165 @@ bool egl_render(void * opaque, SDL_Window * window)
|
|||||||
if (this->sourceChanged)
|
if (this->sourceChanged)
|
||||||
{
|
{
|
||||||
this->sourceChanged = false;
|
this->sourceChanged = false;
|
||||||
if (!egl_texture_init_streaming(
|
if (!egl_texture_setup(
|
||||||
this->textures.desktop,
|
this->textures.desktop,
|
||||||
this->pixFmt,
|
this->pixFmt,
|
||||||
this->format.width,
|
this->format.width,
|
||||||
this->format.height,
|
this->format.height,
|
||||||
this->frameSize
|
this->frameSize,
|
||||||
|
true
|
||||||
))
|
))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
egl_model_set_shader(this->models.desktop, this->shader);
|
egl_model_set_shader(this->models.desktop, this->shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!egl_texture_stream_buffer(this->textures.desktop, this->data))
|
if (!egl_texture_update(this->textures.desktop, this->data))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this->update = false;
|
this->update = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->mouseUpdate)
|
||||||
|
update_mouse_shape(this);
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
egl_model_render(this->models.desktop);
|
egl_model_render(this->models.desktop);
|
||||||
|
|
||||||
|
if (this->mouseVisible)
|
||||||
|
{
|
||||||
|
egl_shader_use(this->mouseShader);
|
||||||
|
glUniform4f(this->mouseUniformLoc, this->mouseX, this->mouseY, this->mouseW, this->mouseH);
|
||||||
|
egl_model_render(this->models.mouse);
|
||||||
|
}
|
||||||
|
|
||||||
eglSwapBuffers(this->display, this->surface);
|
eglSwapBuffers(this->display, this->surface);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_mouse_shape(struct Inst * this)
|
||||||
|
{
|
||||||
|
LG_LOCK(this->mouseLock);
|
||||||
|
this->mouseUpdate = false;
|
||||||
|
|
||||||
|
const LG_RendererCursor cursor = this->mouseCursor;
|
||||||
|
const int width = this->mouseWidth;
|
||||||
|
const int height = this->mouseHeight;
|
||||||
|
//const int pitch = this->mousePitch;
|
||||||
|
const uint8_t * data = this->mouseData;
|
||||||
|
|
||||||
|
// tmp buffer for masked colour
|
||||||
|
uint32_t tmp[width * height];
|
||||||
|
|
||||||
|
switch(cursor)
|
||||||
|
{
|
||||||
|
case LG_CURSOR_MASKED_COLOR:
|
||||||
|
{
|
||||||
|
for(int i = 0; i < width * height; ++i)
|
||||||
|
{
|
||||||
|
const uint32_t c = ((uint32_t *)data)[i];
|
||||||
|
tmp[i] = (c & ~0xFF000000) | (c & 0xFF000000 ? 0x0 : 0xFF000000);
|
||||||
|
}
|
||||||
|
data = (uint8_t *)tmp;
|
||||||
|
// fall through to LG_CURSOR_COLOR
|
||||||
|
//
|
||||||
|
// technically we should also create an XOR texture from the data but this
|
||||||
|
// usage seems very rare in modern software.
|
||||||
|
}
|
||||||
|
|
||||||
|
case LG_CURSOR_COLOR:
|
||||||
|
{
|
||||||
|
egl_texture_setup(
|
||||||
|
this->textures.mouse,
|
||||||
|
EGL_PF_BGRA,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
width * height * 4,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
this->mouseShader = this->shaders.mouse_bgra;
|
||||||
|
egl_texture_update(this->textures.mouse, data);
|
||||||
|
egl_model_set_shader(this->models.mouse, this->mouseShader);
|
||||||
|
this->mouseUniformLoc = egl_shader_get_uniform_location(this->mouseShader, "mouse");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LG_CURSOR_MONOCHROME:
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
const int hheight = height / 2;
|
||||||
|
uint32_t d[width * height];
|
||||||
|
for(int y = 0; y < hheight; ++y)
|
||||||
|
for(int x = 0; x < width; ++x)
|
||||||
|
{
|
||||||
|
const uint8_t * srcAnd = data + (pitch * y) + (x / 8);
|
||||||
|
const uint8_t * srcXor = srcAnd + pitch * hheight;
|
||||||
|
const uint8_t mask = 0x80 >> (x % 8);
|
||||||
|
const uint32_t andMask = (*srcAnd & mask) ? 0xFFFFFFFF : 0xFF000000;
|
||||||
|
const uint32_t xorMask = (*srcXor & mask) ? 0x00FFFFFF : 0x00000000;
|
||||||
|
|
||||||
|
d[y * width + x ] = andMask;
|
||||||
|
d[y * width + x + width * hheight] = xorMask;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*TODO : convert this into a pixel shader
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->textures[MOUSE_TEXTURE]);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT , 4 );
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||||
|
glTexImage2D
|
||||||
|
(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0 ,
|
||||||
|
GL_RGBA,
|
||||||
|
width ,
|
||||||
|
height ,
|
||||||
|
0 ,
|
||||||
|
GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
d
|
||||||
|
);
|
||||||
|
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);
|
||||||
|
|
||||||
|
this->mousePos.w = width;
|
||||||
|
this->mousePos.h = hheight;
|
||||||
|
|
||||||
|
glNewList(this->mouseList, GL_COMPILE);
|
||||||
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, this->textures[MOUSE_TEXTURE]);
|
||||||
|
glLogicOp(GL_AND);
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
glTexCoord2f(0.0f, 0.0f); glVertex2i(0 , 0 );
|
||||||
|
glTexCoord2f(1.0f, 0.0f); glVertex2i(width, 0 );
|
||||||
|
glTexCoord2f(0.0f, 0.5f); glVertex2i(0 , hheight);
|
||||||
|
glTexCoord2f(1.0f, 0.5f); glVertex2i(width, hheight);
|
||||||
|
glEnd();
|
||||||
|
glLogicOp(GL_XOR);
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
glTexCoord2f(0.0f, 0.5f); glVertex2i(0 , 0 );
|
||||||
|
glTexCoord2f(1.0f, 0.5f); glVertex2i(width, 0 );
|
||||||
|
glTexCoord2f(0.0f, 1.0f); glVertex2i(0 , hheight);
|
||||||
|
glTexCoord2f(1.0f, 1.0f); glVertex2i(width, hheight);
|
||||||
|
glEnd();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
|
glEndList();
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->mouseUpdate = true;
|
||||||
|
LG_UNLOCK(this->mouseLock);
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_opt_vsync(void * opaque, const char *value)
|
static void handle_opt_vsync(void * opaque, const char *value)
|
||||||
{
|
{
|
||||||
struct Inst * this = (struct Inst *)opaque;
|
struct Inst * this = (struct Inst *)opaque;
|
||||||
|
@ -212,3 +212,8 @@ void egl_shader_associate_textures(EGL_Shader * shader, const int count)
|
|||||||
}
|
}
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLint egl_shader_get_uniform_location(EGL_Shader * shader, const char * name)
|
||||||
|
{
|
||||||
|
return glGetUniformLocation(shader->shader, name);
|
||||||
|
}
|
@ -34,3 +34,4 @@ bool egl_shader_compile(EGL_Shader * model, const char * vertex_code, size_t ver
|
|||||||
void egl_shader_use (EGL_Shader * shader);
|
void egl_shader_use (EGL_Shader * shader);
|
||||||
|
|
||||||
void egl_shader_associate_textures(EGL_Shader * shader, const int count);
|
void egl_shader_associate_textures(EGL_Shader * shader, const int count);
|
||||||
|
GLint egl_shader_get_uniform_location(EGL_Shader * shader, const char * name);
|
||||||
|
@ -37,17 +37,45 @@ void main()\
|
|||||||
}\
|
}\
|
||||||
";
|
";
|
||||||
|
|
||||||
|
static const char egl_vertex_shader_mouse[] = "\
|
||||||
|
#version 300 es\n\
|
||||||
|
\
|
||||||
|
layout(location = 0) in vec3 vertexPosition_modelspace;\
|
||||||
|
layout(location = 1) in vec2 vertexUV;\
|
||||||
|
\
|
||||||
|
uniform vec4 mouse;\
|
||||||
|
\
|
||||||
|
out highp vec2 uv;\
|
||||||
|
\
|
||||||
|
void main()\
|
||||||
|
{\
|
||||||
|
gl_Position.xyz = vertexPosition_modelspace;\
|
||||||
|
gl_Position.w = 1.0;\
|
||||||
|
\
|
||||||
|
gl_Position.x += 1.0f;\
|
||||||
|
gl_Position.y -= 1.0f;\
|
||||||
|
\
|
||||||
|
gl_Position.x *= mouse.z;\
|
||||||
|
gl_Position.y *= mouse.w;\
|
||||||
|
\
|
||||||
|
gl_Position.x += mouse.x;\
|
||||||
|
gl_Position.y -= mouse.y;\
|
||||||
|
\
|
||||||
|
uv = vertexUV;\
|
||||||
|
}\
|
||||||
|
";
|
||||||
|
|
||||||
static const char egl_fragment_shader_rgba[] = "\
|
static const char egl_fragment_shader_rgba[] = "\
|
||||||
#version 300 es\n\
|
#version 300 es\n\
|
||||||
\
|
\
|
||||||
in highp vec2 uv;\
|
in highp vec2 uv;\
|
||||||
out highp vec3 color;\
|
out highp vec4 color;\
|
||||||
\
|
\
|
||||||
uniform sampler2D sampler1;\
|
uniform sampler2D sampler1;\
|
||||||
\
|
\
|
||||||
void main()\
|
void main()\
|
||||||
{\
|
{\
|
||||||
color = texture(sampler1, uv).rgb;\
|
color = texture(sampler1, uv);\
|
||||||
}\
|
}\
|
||||||
";
|
";
|
||||||
|
|
||||||
@ -55,16 +83,17 @@ static const char egl_fragment_shader_bgra[] = "\
|
|||||||
#version 300 es\n\
|
#version 300 es\n\
|
||||||
\
|
\
|
||||||
in highp vec2 uv;\
|
in highp vec2 uv;\
|
||||||
out highp vec3 color;\
|
out highp vec4 color;\
|
||||||
\
|
\
|
||||||
uniform sampler2D sampler1;\
|
uniform sampler2D sampler1;\
|
||||||
\
|
\
|
||||||
void main()\
|
void main()\
|
||||||
{\
|
{\
|
||||||
highp vec3 tmp = texture(sampler1, uv).rgb;\
|
highp vec4 tmp = texture(sampler1, uv);\
|
||||||
color.r = tmp.b;\
|
color.r = tmp.b;\
|
||||||
color.g = tmp.g;\
|
color.g = tmp.g;\
|
||||||
color.b = tmp.r;\
|
color.b = tmp.r;\
|
||||||
|
color.a = tmp.a;\
|
||||||
}\
|
}\
|
||||||
";
|
";
|
||||||
|
|
||||||
@ -98,4 +127,21 @@ void main()\
|
|||||||
}\
|
}\
|
||||||
";
|
";
|
||||||
|
|
||||||
|
static const char egl_fragment_shader_mask[] = "\
|
||||||
|
#version 300 es\n\
|
||||||
|
\
|
||||||
|
in highp vec2 uv;\
|
||||||
|
out highp vec3 color;\
|
||||||
|
\
|
||||||
|
uniform sampler2D sampler1;\
|
||||||
|
\
|
||||||
|
void main()\
|
||||||
|
{\
|
||||||
|
highp vec3 tmp = texture(sampler1, uv).rgb;\
|
||||||
|
color.r = tmp.b;\
|
||||||
|
color.g = tmp.g;\
|
||||||
|
color.b = tmp.r;\
|
||||||
|
}\
|
||||||
|
";
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -31,6 +31,7 @@ struct EGL_Texture
|
|||||||
{
|
{
|
||||||
enum EGL_PixelFormat pixFmt;
|
enum EGL_PixelFormat pixFmt;
|
||||||
size_t width, height;
|
size_t width, height;
|
||||||
|
bool streaming;
|
||||||
|
|
||||||
int textureCount;
|
int textureCount;
|
||||||
GLuint textures[3];
|
GLuint textures[3];
|
||||||
@ -77,24 +78,21 @@ void egl_texture_free(EGL_Texture ** texture)
|
|||||||
*texture = NULL;
|
*texture = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool egl_texture_init_streaming(EGL_Texture * texture, enum EGL_PixelFormat pixFmt, size_t width, size_t height, size_t bufferSize)
|
bool egl_texture_setup(EGL_Texture * texture, enum EGL_PixelFormat pixFmt, size_t width, size_t height, size_t bufferSize, bool streaming)
|
||||||
{
|
{
|
||||||
if (texture->textureCount > 0)
|
int textureCount;
|
||||||
{
|
|
||||||
glDeleteTextures(texture->textureCount, texture->textures);
|
|
||||||
texture->textureCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->pixFmt = pixFmt;
|
texture->pixFmt = pixFmt;
|
||||||
texture->width = width;
|
texture->width = width;
|
||||||
texture->height = height;
|
texture->height = height;
|
||||||
texture->pboBufferSize = bufferSize;
|
texture->pboBufferSize = bufferSize;
|
||||||
|
texture->streaming = streaming;
|
||||||
|
|
||||||
switch(pixFmt)
|
switch(pixFmt)
|
||||||
{
|
{
|
||||||
case EGL_PF_RGBA:
|
case EGL_PF_RGBA:
|
||||||
case EGL_PF_BGRA:
|
case EGL_PF_BGRA:
|
||||||
texture->textureCount = 1;
|
textureCount = 1;
|
||||||
texture->format = GL_BGRA;
|
texture->format = GL_BGRA;
|
||||||
texture->planes[0][0] = width;
|
texture->planes[0][0] = width;
|
||||||
texture->planes[0][1] = height;
|
texture->planes[0][1] = height;
|
||||||
@ -102,7 +100,7 @@ bool egl_texture_init_streaming(EGL_Texture * texture, enum EGL_PixelFormat pixF
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EGL_PF_YUV420:
|
case EGL_PF_YUV420:
|
||||||
texture->textureCount = 3;
|
textureCount = 3;
|
||||||
texture->format = GL_RED;
|
texture->format = GL_RED;
|
||||||
texture->planes[0][0] = width;
|
texture->planes[0][0] = width;
|
||||||
texture->planes[0][1] = height;
|
texture->planes[0][1] = height;
|
||||||
@ -120,9 +118,20 @@ bool egl_texture_init_streaming(EGL_Texture * texture, enum EGL_PixelFormat pixF
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenTextures(texture->textureCount, texture->textures);
|
if (textureCount > texture->textureCount)
|
||||||
glGenSamplers(texture->textureCount, texture->samplers);
|
{
|
||||||
for(int i = 0; i < texture->textureCount; ++i)
|
if (texture->textureCount > 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(texture->textureCount, texture->textures);
|
||||||
|
glDeleteSamplers(texture->textureCount, texture->samplers);
|
||||||
|
}
|
||||||
|
|
||||||
|
texture->textureCount = textureCount;
|
||||||
|
glGenTextures(texture->textureCount, texture->textures);
|
||||||
|
glGenSamplers(texture->textureCount, texture->samplers);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < textureCount; ++i)
|
||||||
{
|
{
|
||||||
glSamplerParameteri(texture->samplers[i], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glSamplerParameteri(texture->samplers[i], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glSamplerParameteri(texture->samplers[i], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glSamplerParameteri(texture->samplers[i], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
@ -132,45 +141,61 @@ bool egl_texture_init_streaming(EGL_Texture * texture, enum EGL_PixelFormat pixF
|
|||||||
glBindTexture(GL_TEXTURE_2D, texture->textures[i]);
|
glBindTexture(GL_TEXTURE_2D, texture->textures[i]);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, texture->format, texture->planes[i][0], texture->planes[i][1],
|
glTexImage2D(GL_TEXTURE_2D, 0, texture->format, texture->planes[i][0], texture->planes[i][1],
|
||||||
0, texture->format, GL_UNSIGNED_BYTE, NULL);
|
0, texture->format, GL_UNSIGNED_BYTE, NULL);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
}
|
}
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
if (!texture->hasPBO)
|
if (streaming)
|
||||||
{
|
{
|
||||||
glGenBuffers(2, texture->pbo);
|
if (!texture->hasPBO)
|
||||||
texture->hasPBO = true;
|
{
|
||||||
}
|
glGenBuffers(2, texture->pbo);
|
||||||
|
texture->hasPBO = true;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 2; ++i)
|
for(int i = 0; i < 2; ++i)
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->pbo[i]);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->pbo[i]);
|
||||||
glBufferData(
|
glBufferData(
|
||||||
GL_PIXEL_UNPACK_BUFFER,
|
GL_PIXEL_UNPACK_BUFFER,
|
||||||
bufferSize,
|
bufferSize,
|
||||||
NULL,
|
NULL,
|
||||||
GL_DYNAMIC_DRAW
|
GL_DYNAMIC_DRAW
|
||||||
);
|
);
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool egl_texture_stream_buffer(EGL_Texture * texture, const uint8_t * buffer)
|
bool egl_texture_update(EGL_Texture * texture, const uint8_t * buffer)
|
||||||
{
|
{
|
||||||
if (++texture->pboIndex == 2)
|
if (texture->streaming)
|
||||||
texture->pboIndex = 0;
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->pbo[texture->pboIndex]);
|
|
||||||
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, texture->pboBufferSize, buffer);
|
|
||||||
for(int i = 0; i < texture->textureCount; ++i)
|
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->textures[i]);
|
if (++texture->pboIndex == 2)
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->planes[i][0], texture->planes[i][1],
|
texture->pboIndex = 0;
|
||||||
texture->format, GL_UNSIGNED_BYTE, (const void *)texture->offsets[i]);
|
|
||||||
}
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->pbo[texture->pboIndex]);
|
||||||
|
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, texture->pboBufferSize, buffer);
|
||||||
|
for(int i = 0; i < texture->textureCount; ++i)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->textures[i]);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->planes[i][0], texture->planes[i][1],
|
||||||
|
texture->format, GL_UNSIGNED_BYTE, (const void *)texture->offsets[i]);
|
||||||
|
}
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 0; i < texture->textureCount; ++i)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->textures[i]);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->planes[i][0], texture->planes[i][1],
|
||||||
|
texture->format, GL_UNSIGNED_BYTE, buffer + texture->offsets[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ enum EGL_PixelFormat
|
|||||||
bool egl_texture_init(EGL_Texture ** tex);
|
bool egl_texture_init(EGL_Texture ** tex);
|
||||||
void egl_texture_free(EGL_Texture ** tex);
|
void egl_texture_free(EGL_Texture ** tex);
|
||||||
|
|
||||||
bool egl_texture_init_streaming(EGL_Texture * texture, enum EGL_PixelFormat pixfmt, size_t width, size_t height, size_t bufferSize);
|
bool egl_texture_setup (EGL_Texture * texture, enum EGL_PixelFormat pixfmt, size_t width, size_t height, size_t bufferSize, bool streaming);
|
||||||
bool egl_texture_stream_buffer (EGL_Texture * texture, const uint8_t * buffer);
|
bool egl_texture_update(EGL_Texture * texture, const uint8_t * buffer);
|
||||||
void egl_texture_bind (EGL_Texture * texture);
|
void egl_texture_bind (EGL_Texture * texture);
|
||||||
int egl_texture_count (EGL_Texture * texture);
|
int egl_texture_count (EGL_Texture * texture);
|
Loading…
Reference in New Issue
Block a user