39#include <glm/gtc/matrix_transform.hpp>
40#include <glm/gtc/type_ptr.hpp>
53#define GRIDPOINTSTEXT 1
56#define GRIDPOINTSIZE 3
57#define GRIDPOINTOFFSET 4
58#define GRIDPOINTSTXTSIZE 14
59#define GRIDPOINTBG clrTransparent
60#define GRIDPOINTCLR 0xFFFF0000
67 col.a = ((colARGB & 0xFF000000) >> 24) / 255.0;
68 col.r = ((colARGB & 0x00FF0000) >> 16) / 255.0;
69 col.g = ((colARGB & 0x0000FF00) >> 8 ) / 255.0;
70 col.b = ((colARGB & 0x000000FF) ) / 255.0;
80 GL_CHECK(glUseProgram(
m_id));
85 const char *vertexCode = NULL;
86 const char *fragmentCode = NULL;
107 LOGERROR(
"openglosd: %s: unknown shader type", __FUNCTION__);
111 if (vertexCode == NULL || fragmentCode == NULL) {
112 LOGERROR(
"openglosd: %s: error reading shader", __FUNCTION__);
116 if (!
Compile(vertexCode, fragmentCode)) {
117 LOGERROR(
"openglosd: %s: error compiling shader", __FUNCTION__);
126 GL_CHECK(glUniform1f(glGetUniformLocation(
m_id, name), value));
131 GL_CHECK(glUniform1i(glGetUniformLocation(
m_id, name), value));
136 GL_CHECK(glUniform2f(glGetUniformLocation(
m_id, name), x, y));
141 GL_CHECK(glUniform3f(glGetUniformLocation(
m_id, name), x, y, z));
146 GL_CHECK(glUniform4f(glGetUniformLocation(
m_id, name), x, y, z, w));
151 GL_CHECK(glUniformMatrix4fv(glGetUniformLocation(
m_id, name), 1, GL_FALSE, glm::value_ptr(matrix)));
156 GLuint sVertex, sFragment;
159 GL_CHECK(sVertex = glCreateShader(GL_VERTEX_SHADER));
160 GL_CHECK(glShaderSource(sVertex, 1, &vertexCode, NULL));
161 GL_CHECK(glCompileShader(sVertex));
166 GL_CHECK(sFragment = glCreateShader(GL_FRAGMENT_SHADER));
167 GL_CHECK(glShaderSource(sFragment, 1, &fragmentCode, NULL));
168 GL_CHECK(glCompileShader(sFragment));
173 GL_CHECK(
m_id = glCreateProgram());
174 GL_CHECK(glAttachShader(
m_id, sVertex));
175 GL_CHECK(glAttachShader(
m_id, sFragment));
176 GL_CHECK(glBindAttribLocation(
m_id, 0,
"position"));
177 GL_CHECK(glBindAttribLocation(
m_id, 1,
"texCoords"));
178 GL_CHECK(glLinkProgram(
m_id));
183 GL_CHECK(glDeleteShader(sVertex));
184 GL_CHECK(glDeleteShader(sFragment));
190 GLchar infoLog[1024];
192 GL_CHECK(glGetShaderiv(
object, GL_COMPILE_STATUS, &success));
194 GL_CHECK(glGetShaderInfoLog(
object, 1024, NULL, infoLog));
195 LOGERROR(
"openglosd: %s: Compile-time error: Type: %d - %s", __FUNCTION__,
m_type, infoLog);
199 GL_CHECK(glGetProgramiv(
object, GL_LINK_STATUS, &success));
201 GL_CHECK(glGetProgramInfoLog(
object, 1024, NULL, infoLog));
202 LOGERROR(
"openglosd: %s: Link-time error: Type: %d - %s", __FUNCTION__,
m_type, infoLog);
209#define KERNING_UNKNOWN (-10000)
214 : m_charCode(charCode),
215 m_bearingLeft(ftGlyph->left),
216 m_bearingTop(ftGlyph->top),
217 m_width(ftGlyph->bitmap.width),
218 m_height(ftGlyph->bitmap.rows),
219 m_pBuffer(ftGlyph->bitmap.buffer),
220 m_advanceX(ftGlyph->root.advance.x >> 16)
227 GL_CHECK(glDeleteTextures(1, &
m_texture));
246 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_texture));
252 GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
254 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_texture));
256 GL_CHECK(glTexImage2D(
269 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
270 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
271 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
272 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
273 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
274 GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
283 GL_CHECK(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxAtlasWidth));
285 FT_Set_Pixel_Sizes(face, 0, height);
286 FT_GlyphSlot g = face->glyph;
293 if (FT_Load_Char(face, i, FT_LOAD_NO_BITMAP)) {
301 if (FT_Stroker_New(g->library, &stroker)) {
302 LOGERROR(
"openglosd: %s: FT_Stroker_New error!", __FUNCTION__);
306 float outlineWidth = 0.25f;
307 FT_Stroker_Set(stroker, (
int)(outlineWidth * 64),
308 FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
310 if (FT_Get_Glyph(g, &ftGlyph)) {
311 LOGERROR(
"openglosd: %s: FT_Get_Glyph error!", __FUNCTION__);
315 if (FT_Glyph_StrokeBorder(&ftGlyph, stroker, 0, 1)) {
316 LOGERROR(
"openglosd: %s: FT_Glyph_StrokeBoder error!", __FUNCTION__);
320 FT_Stroker_Done(stroker);
322 if (FT_Glyph_To_Bitmap(&ftGlyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
323 LOGERROR(
"openglosd: %s: FT_Glyph_To_Bitmap error!", __FUNCTION__);
327 FT_BitmapGlyph bGlyph = (FT_BitmapGlyph)ftGlyph;
329 if (rowW + bGlyph->bitmap.width + 1 >= (
unsigned int)maxAtlasWidth) {
335 rowW += bGlyph->bitmap.width + 1;
336 rowH = std::max(rowH, (
int)bGlyph->bitmap.rows);
338 FT_Done_Glyph(ftGlyph);
346 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_texture));
349 GL_CHECK(glTexImage2D(
361 GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
362 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
363 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
364 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
365 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
374 if (FT_Load_Char(face, i, FT_LOAD_NO_BITMAP)) {
375 LOGWARNING(
"openglosd: %s: Loading char %c failed!", __FUNCTION__, i);
382 if (FT_Stroker_New(g->library, &stroker)) {
383 LOGERROR(
"openglosd: %s: FT_Stroker_New error!", __FUNCTION__);
387 float outlineWidth = 0.25f;
388 FT_Stroker_Set(stroker, (
int)(outlineWidth * 64),
389 FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
391 if (FT_Get_Glyph(g, &ftGlyph)) {
392 LOGERROR(
"openglosd: %s: FT_Get_Glyph error!", __FUNCTION__);
396 if (FT_Glyph_StrokeBorder(&ftGlyph, stroker, 0, 1)) {
397 LOGERROR(
"openglosd: %s: FT_Glyph_StrokeBoder error!", __FUNCTION__);
401 FT_Stroker_Done(stroker);
403 if (FT_Glyph_To_Bitmap(&ftGlyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
404 LOGERROR(
"openglosd: %s: FT_Glyph_To_Bitmap error!", __FUNCTION__);
407 FT_BitmapGlyph bGlyph = (FT_BitmapGlyph)ftGlyph;
410 if (offsetX + bGlyph->bitmap.width + 1 >= (
unsigned int)maxAtlasWidth) {
416 GL_CHECK(glTexSubImage2D(
421 bGlyph->bitmap.width,
425 bGlyph->bitmap.buffer
429 rowH = std::max(rowH, (
int)bGlyph->bitmap.rows);
430 offsetX += bGlyph->bitmap.width + 1;
432 FT_Done_Glyph(ftGlyph);
435 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
436 LOGDEBUG2(
L_OPENGL,
"openglosd: %s: Created a %d x %d (%d kB) FontAtlas for fontsize %d, rowH %d, rowW %d",
442 GL_CHECK(glDeleteTextures(1, &
m_texture));
460 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_texture));
476 LOGERROR(
"openglosd: %s: failed to open %s!", __FUNCTION__, *
m_name);
484 charcode = FT_Get_First_Char(
m_face, &gindex);
487 while (gindex != 0) {
489 charcode = FT_Get_Next_Char(
m_face, charcode, &gindex);
490 minIndex = std::min(minIndex, (
int)gindex);
491 maxIndex = std::max(maxIndex, (
int)gindex);
498 LOGDEBUG2(
L_OPENGL,
"openglosd: %s: Created new font: %s (%d) height: %d, bottom: %d - %d chars (%d - %d)", __FUNCTION__,
m_name,
m_size,
m_height,
m_bottom, count, minIndex, maxIndex);
514 if (!strcmp(font->
Name(), name) && charHeight == font->
Size()) {
517 font =
new cOglFont(name, charHeight);
525 if (FT_Init_FreeType(&
s_ftLib)) {
526 LOGERROR(
"openglosd: %s: failed to initialize FreeType library!", __FUNCTION__);
540 LOGERROR(
"openglosd: %s: failed to deinitialize FreeType library!", __FUNCTION__);
548 if (charCode == 0xA0)
553 if (g->CharCode() == charCode) {
558 FT_UInt glyphIndex = FT_Get_Char_Index(
m_face, charCode);
560 FT_Int32 loadFlags = FT_LOAD_NO_BITMAP;
562 int error = FT_Load_Glyph(
m_face, glyphIndex, loadFlags);
570 error = FT_Stroker_New(
s_ftLib, &stroker);
575 float outlineWidth = 0.25f;
576 FT_Stroker_Set(stroker, (
int)(outlineWidth * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
578 error = FT_Get_Glyph(
m_face->glyph, &ftGlyph);
584 error = FT_Glyph_StrokeBorder(&ftGlyph, stroker, 0, 1);
589 FT_Stroker_Done(stroker);
591 error = FT_Glyph_To_Bitmap(&ftGlyph, FT_RENDER_MODE_NORMAL, 0, 1);
600 FT_Done_Glyph(ftGlyph);
608 if (glyph && prevSym) {
612 FT_UInt glyphIndex = FT_Get_Char_Index(
m_face, glyph->
CharCode());
613 FT_UInt glyphIndexPrev = FT_Get_Char_Index(
m_face, prevSym);
614 FT_Get_Kerning(
m_face, glyphIndexPrev, glyphIndex, FT_KERNING_DEFAULT, &delta);
615 kerning = delta.x / 64;
626cOglFb::cOglFb(GLint width, GLint height, GLint viewPortWidth, GLint viewPortHeight)
629 m_viewPortWidth(viewPortWidth),
630 m_viewPortHeight(viewPortHeight)
639 GL_CHECK(glDeleteTextures(1, &
m_texture));
647 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_texture));
648 GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
m_width,
m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
649 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
650 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
651 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
652 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
656 GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
m_texture, 0));
659 GL_CHECK(fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER));
660 if (fbstatus != GL_FRAMEBUFFER_COMPLETE) {
661 LOGERROR(
"openglosd: %s: Framebuffer is not complete!", __FUNCTION__);
679 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
680 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
687 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_texture));
697 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_texture));
698 GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
m_width,
m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
699 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
700 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
701 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
702 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
706 GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
m_texture, 0));
709 GL_CHECK(fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER));
710 if (fbstatus != GL_FRAMEBUFFER_COMPLETE) {
711 LOGERROR(
"openglosd: %s: Framebuffer is not complete!", __FUNCTION__);
721 GL_CHECK(glFinish());
722 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
723 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
780 GL_CHECK(glGenBuffers(1, &
m_vbo));
781 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
m_vbo));
792 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
799 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
m_vbo));
810 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
820 GL_CHECK(glEnable(GL_BLEND));
821 GL_CHECK(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
826 GL_CHECK(glDisable(GL_BLEND));
855 glm::mat4 projection = glm::ortho(0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -1.0f, 1.0f);
863 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
m_vbo));
865 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
872 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER,
m_vbo));
873 GL_CHECK(glBufferData(GL_ARRAY_BUFFER,
sizeof(GLfloat) * (
m_sizeVertex1 +
m_sizeVertex2) * count, vertices, GL_DYNAMIC_DRAW));
874 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
909 GL_CHECK(glFinish());
924 GLfloat texX2 = texX1 + 1.0f;
926 GLfloat texY2 = texY1 + 1.0f;
933 texY2 = texY1 + pageHeight;
936 GLfloat quadVertices[] = {
938 x1, y1, texX1, texY2,
939 x1, y2, texX1, texY1,
940 x2, y2, texX2, texY1,
942 x1, y1, texX1, texY2,
943 x2, y2, texX2, texY1,
958 GL_CHECK(glEnable(GL_SCISSOR_TEST));
962 GL_CHECK(glDisable(GL_SCISSOR_TEST));
980 GLfloat texX1 = 0.0f;
981 GLfloat texX2 = 1.0f;
982 GLfloat texY1 = 1.0f;
983 GLfloat texY2 = 0.0f;
985 GLfloat quadVertices[] = {
987 x1, y1, texX1, texY1,
988 x1, y2, texX1, texY2,
989 x2, y2, texX2, texY2,
991 x1, y1, texX1, texY1,
992 x2, y2, texX2, texY2,
1011 GL_CHECK(glFinish());
1029 GL_CHECK(glClearColor(col.r, col.g, col.b, col.a));
1030 GL_CHECK(glClear(GL_COLOR_BUFFER_BIT));
1041 GL_CHECK(glClearColor(col.r, col.g, col.b, col.a));
1042 GL_CHECK(glClear(GL_COLOR_BUFFER_BIT));
1058 GLfloat vertices[] = {
1093 int numVertices = 0;
1094 GLfloat *vertices = NULL;
1141 numVertices = size/2;
1142 GLfloat radiusX = (GLfloat)
m_width / 2;
1143 GLfloat radiusY = (GLfloat)
m_height / 2;
1144 GLfloat *vertices =
new GLfloat[size];
1145 vertices[0] =
m_x + radiusX;
1146 vertices[1] =
m_y + radiusY;
1147 for (
int i=0; i <= 180; i++) {
1148 vertices[2 * i + 2] =
m_x + radiusX + (GLfloat)cos(2 * i * M_PI / 180.0f) * radiusX;
1149 vertices[2 * i + 3] =
m_y + radiusY - (GLfloat)sin(2 * i * M_PI / 180.0f) * radiusY;
1157 numVertices = size / 2;
1158 GLfloat radiusX = (GLfloat)
m_width;
1159 GLfloat radiusY = (GLfloat)
m_height;
1162 GLint startAngle = 0;
1163 GLfloat *vertices =
new GLfloat[size];
1214 for (
int i = 0; i <= 45; i++) {
1215 vertices[2 * i + 2] =
m_x + transX + (GLfloat)cos((2 * i + startAngle) * M_PI / 180.0f) * radiusX;
1216 vertices[2 * i + 3] =
m_y + transY - (GLfloat)sin((2 * i + startAngle) * M_PI / 180.0f) * radiusY;
1224 numVertices = size / 2;
1225 GLfloat radiusX = 0.0f;
1226 GLfloat radiusY = 0.0f;
1229 GLint startAngle = 0;
1230 GLfloat *vertices =
new GLfloat[size];
1236 vertices[1] =
m_y + radiusY;
1241 radiusX = (GLfloat)
m_width / 2;
1243 vertices[0] =
m_x + radiusX;
1244 vertices[1] =
m_y + radiusY;
1252 vertices[0] =
m_x + radiusX;
1253 vertices[1] =
m_y + radiusY;
1259 radiusX = (GLfloat)
m_width / 2;
1261 vertices[0] =
m_x + radiusX;
1269 for (
int i=0; i <= 90; i++) {
1270 vertices[2 * i + 2] =
m_x + transX + (GLfloat)cos((2 * i + startAngle) * M_PI / 180.0f) * radiusX;
1271 vertices[2 * i + 3] =
m_y + transY - (GLfloat)sin((2 * i + startAngle) * M_PI / 180.0f) * radiusY;
1292 bool falling =
m_type & 0x02;
1293 bool vertical =
m_type & 0x04;
1298 int numVertices = steps + 2;
1299 GLfloat *vertices =
new GLfloat[numVertices * 2];
1309 vertices[0] = (GLfloat)
m_x;
1310 vertices[1] = (GLfloat)
m_y;
1314 vertices[0] = (GLfloat)
m_x;
1320 vertices[1] = (GLfloat)
m_y;
1323 vertices[0] = (GLfloat)(
m_x);
1324 vertices[1] = (GLfloat)(
m_y);
1328 for (
int i = 0; i <= steps; i++) {
1329 GLfloat c = cos(i * M_PI / steps);
1333 vertices[2 * i + 2] = (GLfloat)
m_x + (GLfloat)
m_width / 2.0f + (GLfloat)
m_width * c / 2.0f;
1334 vertices[2 * i + 3] = (GLfloat)
m_y + (GLfloat)i * ((GLfloat)
m_height) / steps ;
1336 vertices[2 * i + 2] = (GLfloat)
m_x + (GLfloat)i * ((GLfloat)
m_width) / steps ;
1337 vertices[2 * i + 3] = (GLfloat)
m_y + (GLfloat)
m_height / 2.0f + (GLfloat)
m_height * c / 2.0f;
1378 int fontHeight = f->
Height();
1379 int bottom = f->
Bottom();
1381 FT_ULong prevSym = 0;
1385 int unknown_char = 0;
1395 if (!unknown_char) {
1397 std::vector<GLfloat> vertices;
1398 vertices.reserve( 4 * 6 *
m_length);
1408 LOGWARNING(
"openglosd: %s: could not load glyph %lx", __FUNCTION__, sym);
1415 kerning = f->
Kerning(g, prevSym);
1420 GLfloat w = g->
Width();
1423 vertices.push_back(x2);
1424 vertices.push_back(y2);
1425 vertices.push_back(g->
OffsetX());
1426 vertices.push_back(g->
OffsetY());
1428 vertices.push_back(x2 + w);
1429 vertices.push_back(y2);
1431 vertices.push_back(g->
OffsetY());
1433 vertices.push_back(x2);
1434 vertices.push_back(y2 + h);
1435 vertices.push_back(g->
OffsetX());
1438 vertices.push_back(x2 + w);
1439 vertices.push_back(y2);
1441 vertices.push_back(g->
OffsetY());
1443 vertices.push_back(x2);
1444 vertices.push_back(y2 + h);
1445 vertices.push_back(g->
OffsetX());
1448 vertices.push_back(x2 + w);
1449 vertices.push_back(y2 + h);
1465 LOGDEBUG2(
L_OPENGL,
"openglosd: %s: char %d is not on the texture atlas, use single draw", __FUNCTION__, unknown_char);
1470 LOGWARNING(
"openglosd: %s: could not load glyph %lx", __FUNCTION__, sym);
1477 kerning = f->
Kerning(g, prevSym);
1482 GLfloat x2 = x1 + g->
Width();
1483 GLfloat y2 = y1 + g->
Height();
1485 GLfloat vertices[] = {
1506 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
1519 GL_CHECK(glGenTextures(1, &texture));
1520 GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture));
1521 GL_CHECK(glTexImage2D(
1532 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1533 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1534 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1535 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1536 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
1543 GLfloat quadVertices[] = {
1559 GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture));
1569 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
1570 GL_CHECK(glDeleteTextures(1, &texture));
1586 GLfloat quadVertices[] = {
1603 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_pImageRef->texture));
1615 GL_CHECK(glGenTextures(1, &
m_pImageRef->texture));
1616 GL_CHECK(glBindTexture(GL_TEXTURE_2D,
m_pImageRef->texture));
1617 GL_CHECK(glTexImage2D(
1628 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
1629 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1630 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
1631 GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
1632 GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
1639 GL_CHECK(glDeleteTextures(1, &
m_pImageRef->texture));
1648 : cThread(
"oglThread"),
1649 m_startWait(startWait),
1650 m_maxCacheSize(maxCacheSize * 1024 * 1024),
1651 m_pRender(device->Render())
1677 cCondWait::SleepMs(10);
1679 bool doSignal =
false;
1697 LOGERROR(
"openglosd: %s: cannot store image, no cache set", __FUNCTION__);
1702 LOGERROR(
"openglosd: %s: cannot store image of %dpx x %dpx (maximum size is %dpx x %dpx) - falling back to cOsdProvider::StoreImageData()",
1707 int imgSize = image.Width() * image.Height();
1708 int newMemUsed = imgSize *
sizeof(tColor) +
m_memCached;
1712 LOGERROR(
"openglosd: %s: Maximum size for GPU cache reached. Used: %.2fMB Max: %.2fMB", __FUNCTION__, cachedMB, maxMB);
1720 tColor *argb = MALLOC(tColor, imgSize);
1722 LOGERROR(
"openglosd: %s: memory allocation of %d kb for OSD image failed", __FUNCTION__, (
int)(imgSize *
sizeof(tColor) / 1024));
1728 memcpy(argb, image.Data(),
sizeof(tColor) * imgSize);
1731 imageRef->width = image.Width();
1732 imageRef->height = image.Height();
1735 cTimeMs timer(5000);
1736 while (imageRef->used && imageRef->texture == 0 && !timer.TimedOut())
1737 cCondWait::SleepMs(2);
1739 if (imageRef->texture == GL_NONE) {
1740 LOGERROR(
"openglosd: %s: failed to store OSD image texture! (%s)", __FUNCTION__, timer.TimedOut() ?
"timed out" :
"allocation failed");
1790 int imgSize = imageRef->width * imageRef->height *
sizeof(tColor);
1801 LOGERROR(
"openglosd: %s: Could not initiate OpenGL context", __FUNCTION__);
1808 LOGERROR(
"openglosd: %s: Could not initiate shaders", __FUNCTION__);
1815 LOGERROR(
"openglosd: %s: Vertex Buffers NOT initialized", __FUNCTION__);
1828 LOGINFO(
"OpenGL context initialized");
1830 uint64_t startFlush = 0;
1831 uint64_t endFlush = 0;
1832 bool timeReset =
false;
1845 uint64_t start = cTimeMs::Now();
1846 if (strcmp(cmd->
Description(),
"InitFramebuffer") == 0 || timeReset) {
1847 startFlush = cTimeMs::Now();
1853 __FUNCTION__, 15, cmd->
Description(), (
int)(cTimeMs::Now() - start), (
int)(
m_commands.size()), cTimeMs::Now());
1855 if (strcmp(cmd->
Description(),
"Copy buffer to OutputFramebuffer") == 0) {
1856 endFlush = cTimeMs::Now();
1858 LOGDEBUG2(
L_OPENGL_TIME,
"openglosd: %s: OSD Flush %dms, time %" PRIu64
"", __FUNCTION__, (
int)(endFlush - startFlush), cTimeMs::Now());
1877 EGL_CHECK(eglMakeCurrent(
m_pRender->EglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
1894 GL_CHECK(
LOGDEBUG2(
L_OPENGL,
" GL Extensions: \"%s\"", glGetString(GL_EXTENSIONS)));
1895 GL_CHECK(
LOGDEBUG2(
L_OPENGL,
" GL Renderer: \"%s\"", glGetString(GL_RENDERER)));
1898 GL_CHECK(glDisable(GL_DEPTH_TEST));
1906 for (
int i = 0; i <
stCount; i++) {
1919 for (
int i = 0; i <
stCount; i++)
1925 for (
int i = 0; i <
vbCount; i++) {
1938 for (
int i=0; i <
vbCount; i++) {
1956 : cPixmap(layer, viewPort, drawPort),
1957 m_pOglThread(oglThread)
1959 int width = drawPort.IsEmpty() ? viewPort.Width() : drawPort.Width();
1960 int height = drawPort.IsEmpty() ? viewPort.Height() : drawPort.Height();
1963 LOGWARNING(
"openglosd: %s: cannot allocate pixmap of %dpx x %dpx, clipped to %dpx x %dpx!", __FUNCTION__,
1965 width = std::min(width,
m_pOglThread->MaxTextureSize());
1966 height = std::min(height,
m_pOglThread->MaxTextureSize());
1973 m_pTinyfont = cFont::CreateFont(Setup.FontOsd, GRIDPOINTSTXTSIZE);
1990 cPixmap::MarkViewPortDirty(rect);
1996 cPixmap::SetClean();
2002 cPixmap::SetLayer(layer);
2008 alpha = constrain(alpha, ALPHA_TRANSPARENT, ALPHA_OPAQUE);
2009 if (alpha != cPixmap::Alpha()) {
2010 cPixmap::SetAlpha(alpha);
2017 cPixmap::SetTile(tile);
2023 cPixmap::SetViewPort(rect);
2029 cPixmap::SetDrawPortPoint(point, dirty);
2042 MarkDrawPortDirty(DrawPort());
2053 MarkDrawPortDirty(DrawPort());
2066void cOglPixmap::DrawScaledImage(
const cPoint &point,
const cImage &image,
double factorX,
double factorY, __attribute__ ((unused))
bool antiAlias)
2071 tColor *argb = MALLOC(tColor, image.Width() * image.Height());
2074 memcpy(argb, image.Data(),
sizeof(tColor) * image.Width() * image.Height());
2078 DrawGridRect(cRect(point.X(), point.Y(), image.Width() * factorX, image.Height() * factorY), GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2081 MarkDrawPortDirty(cRect(point, cSize(image.Width() * factorX, image.Height() * factorY)).Intersected(DrawPort().Size()));
2084void cOglPixmap::DrawScaledImage(
const cPoint &point,
int imageHandle,
double factorX,
double factorY, __attribute__ ((unused))
bool antiAlias)
2089 if (imageHandle < 0 && m_pOglThread->GetImageRef(imageHandle)) {
2090 sOglImage *img =
m_pOglThread->GetImageRef(imageHandle);
2093 DrawGridRect(cRect(point.X(), point.Y(), img->width * factorX, img->height * factorY), GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2096 MarkDrawPortDirty(cRect(point, cSize(img->width * factorX, img->height * factorY)).Intersected(DrawPort().Size()));
2102 cRect r(point.X(), point.Y(), 1, 1);
2105 DrawGridRect(cRect(r.X(), r.Y(), 0, 0), GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2108 MarkDrawPortDirty(r);
2117 bool specialColors = colorFg || colorBg;
2118 tColor *argb = MALLOC(tColor, bitmap.Width() * bitmap.Height());
2123 for (
int py = 0; py < bitmap.Height(); py++)
2124 for (
int px = 0; px < bitmap.Width(); px++) {
2125 tIndex index = *bitmap.Data(px, py);
2126 *p++ = (!index && overlay) ? clrTransparent :
2127 (specialColors ? (index == 0 ? colorBg : index == 1 ? colorFg :
2128 bitmap.Color(index)) : bitmap.Color(index));
2133 DrawGridRect(cRect(point.X(), point.Y(), bitmap.Width(), bitmap.Height()), GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2137 MarkDrawPortDirty(cRect(cPoint(point.X(), point.Y()), cSize(bitmap.Width(), bitmap.Height())).Intersected(DrawPort().Size()));
2140void cOglPixmap::DrawText(
const cPoint &point,
const char *s, tColor colorFg, tColor colorBg,
const cFont *font,
int width,
int height,
int alignment)
2142 DrawTextInternal(point, s, colorFg, colorBg, font, width, height, alignment,
false);
2146void cOglPixmap::DrawGridText(
const cPoint &point,
const char *s, tColor colorFg, tColor colorBg,
const cFont *font,
int width,
int height,
int alignment)
2148 DrawTextInternal(point, s, colorFg, colorBg, font, width, height, alignment,
true);
2152void cOglPixmap::DrawTextInternal(
const cPoint &point,
const char *s, tColor colorFg, tColor colorBg,
const cFont *font,
int width,
int height,
int alignment,
bool isGridText)
2158 int len = s ? Utf8StrLen(s) : 0;
2159 unsigned int *symbols = MALLOC(
unsigned int, len + 1);
2164 Utf8ToArray(s, symbols, len + 1);
2170 int w = font->Width(s);
2171 int h = font->Height();
2173 int cw = width ? width : w;
2174 int ch = height ? height : h;
2177 if (width > ViewPort().Width() && !x && !isGridText)
2178 x = ViewPort().Width() - w;
2180 cRect r(x, y, cw, ch);
2182 if (colorBg != clrTransparent)
2185 if (width || height)
2189 if ((alignment & taLeft) != 0) {
2190 if ((alignment & taBorder) != 0)
2191 x += std::max(h / TEXT_ALIGN_BORDER, 1);
2192 }
else if ((alignment & taRight) != 0) {
2195 if ((alignment & taBorder) != 0)
2196 x -= std::max(h / TEXT_ALIGN_BORDER, 1);
2199 x += (width - w) / 2;
2204 if ((alignment & taTop) != 0)
2206 else if ((alignment & taBottom) != 0) {
2211 y += (height - h) / 2;
2219 DrawGridRect(cRect(x, y, cw, ch), GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2223 MarkDrawPortDirty(r);
2234 DrawGridRect(rect, GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2238 MarkDrawPortDirty(rect);
2249 DrawGridRect(rect, GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2253 MarkDrawPortDirty(rect);
2264 DrawGridRect(rect, GRIDPOINTOFFSET, GRIDPOINTSIZE, GRIDPOINTCLR, GRIDPOINTBG, m_pTinyfont);
2268 MarkDrawPortDirty(rect);
2273 LOGWARNING(
"openglosd: %s: %d %d %d not implemented in OpenGl OSD", __FUNCTION__, pixmap->ViewPort().X(), source.X(), dest.X());
2278 LOGWARNING(
"openglosd: %s: %d %d %d not implemented in OpenGl OSD", __FUNCTION__, pixmap->ViewPort().X(), source.X(), dest.X());
2283 LOGWARNING(
"openglosd: %s: %d %d not implemented in OpenGl OSD", __FUNCTION__, source.X(), dest.X());
2288 LOGWARNING(
"openglosd: %s: %d %d not implemented in OpenGl OSD", __FUNCTION__, source.X(), dest.X());
2292void cOglPixmap::DrawGridRect(
const cRect &rect,
int offset,
int size, tColor clr, tColor bg,
const cFont *font)
2294 int x1 = rect.X() + offset;
2295 int x2 = rect.X() + rect.Width() + offset;
2297 int y2 = rect.Y() + rect.Height();
2302 sprintf(p1,
"%d.%d", x1, y1);
2303 sprintf(p2,
"%d.%d", x2, y1);
2304 sprintf(p3,
"%d.%d", x1, y2);
2305 sprintf(p4,
"%d.%d", x2, y2);
2308#ifdef GRIDPOINTSTEXT
2309 DrawGridText(cPoint(x1, y1), p1, clr, bg, font);
2311 if (Rect.Width() && Rect.Height()) {
2315#ifdef GRIDPOINTSTEXT
2316 DrawGridText(cPoint(x2, y1), p2, clr, bg, font);
2317 DrawGridText(cPoint(x1, y2), p3, clr, bg, font);
2318 DrawGridText(cPoint(x2, y2), p4, clr, bg, font);
2330 : cOsd(left, top, level),
2331 m_pOglThread(oglThread),
2332 m_isSubtitleOsd(level == 10 ? true : false),
2339 LOGDEBUG2(
L_OSD,
"openglosd: %s: New Osd %p osdLeft %d osdTop %d screenWidth %d screenHeight %d", __FUNCTION__,
this, left, top, osdWidth, osdHeight);
2354 LOGDEBUG2(
L_OSD,
"openglosd: %s: Delete Osd %p", __FUNCTION__,
this);
2367 for (
int i = 0; i < numAreas; i++)
2368 r.Combine(cRect(areas[i].x1, areas[i].y1, areas[i].Width(), areas[i].Height()));
2370 tArea area = { r.Left(), r.Top(), r.Right(), r.Bottom(), 32 };
2378 cCondWait initiated;
2382 return cOsd::SetAreas(&area, 1);
2392 if (cOsd::AddPixmap(p)) {
2419 if (Pixmap->Layer() >= 0)
2424 cOsd::DestroyPixmap(Pixmap);
2436 LOGDEBUG2(
L_OSD,
"openglosd: %s: Flush Osd %p", __FUNCTION__,
this);
2463 for (
int layer = 0; layer < MAXPIXMAPLAYERS; layer++) {
2477 bool alphablending = layer == 0 ? false :
true;
2506 std::unique_ptr<cBitmap> scaledBitmap;
2507 const cBitmap *b = &Bitmap;
2509 if (!DoubleEqual(FactorX, 1.0) || !DoubleEqual(FactorY, 1.0)) {
2510 scaledBitmap.reset(Bitmap.Scaled(FactorX, FactorY, AntiAlias));
2511 b = scaledBitmap.get();
2519 xNew -= viewport.X();
2521 yNew -= viewport.Y();
float OffsetY(void) const
float OffsetX(void) const
virtual bool Execute(void)
cOglOutputFb * m_pOutputFramebuffer
virtual bool Execute(void)
cSoftHdDevice * m_pDevice
virtual bool Execute(void)
GLfloat * CreateVerticesFull(int &)
GLfloat * CreateVerticesHalf(int &)
GLfloat * CreateVerticesQuadrant(int &)
virtual bool Execute(void)
virtual bool Execute(void)
virtual bool Execute(void)
virtual bool Execute(void)
unsigned int * m_pSymbols
virtual bool Execute(void)
virtual bool Execute(void)
virtual bool Execute(void)
virtual bool Execute(void)
virtual bool Execute(void)
cOglOutputFb * m_pOutputFramebuffer
virtual bool Execute(void)
virtual bool Execute(void)
virtual bool Execute(void)
virtual bool Execute(void)=0
virtual const char * Description(void)=0
virtual void Unbind(void)
GLint ViewportHeight(void)
cOglFb(GLint, GLint, GLint, GLint)
GLint ViewportWidth(void)
cOglFontAtlas(FT_Face, int)
cOglAtlasGlyph * GetGlyph(int) const
virtual ~cOglFontAtlas(void)
cOglAtlasGlyph * m_pGlyph[MAX_CHARCODE - MIN_CHARCODE+1]
static void Cleanup(void)
cOglFont(const char *, int)
cOglFontAtlas * Atlas(void)
cOglGlyph * Glyph(FT_ULong) const
static cOglFont * Get(const char *, int)
int Kerning(cOglGlyph *glyph, FT_ULong prevSym) const
cList< cOglGlyph > m_glyphCache
static FT_Library s_ftLib
static cList< cOglFont > * s_pFonts
cOglGlyph(FT_ULong, FT_BitmapGlyph)
unsigned char * m_pBuffer
int BearingTop(void) const
void SetKerningCache(FT_ULong, int)
int BearingLeft(void) const
int GetKerningCache(FT_ULong)
cVector< tKerning > m_pKerningCache
std::shared_ptr< cOglThread > m_pOglThread
pointer to thread, which executes the commands
bool m_isSubtitleOsd
true, if this is a subtitle osd
cSoftHdDevice * m_pDevice
pointer to cSofthdDevice
cOglFb * m_pBufferFramebuffer
all pixmaps are composed onto this framebuffer after each other, before this one is blit onto the OSD...
static cOglOutputFb * OutputFramebuffer
main OSD output framebuffer - this keeps our finished "OSD" (one per OSD)
virtual eOsdError SetAreas(const tArea *, int)
cRect m_pDirtyViewport
the dirty viewport
virtual void DrawScaledBitmap(int, int, const cBitmap &, double, double, bool AntiAlias=false)
virtual cPixmap * CreatePixmap(int, const cRect &, const cRect &DrawPort=cRect::Null)
cVector< cOglPixmap * > m_pOglPixmaps
array of pixmaps
cOglOsd(int, int, uint, std::shared_ptr< cOglThread >, cSoftHdDevice *)
cSize m_maxPixmapSize
maximum allowed size of a pixmap (depends on the maximum OpenGL texture size)
virtual void DestroyPixmap(cPixmap *)
virtual void Unbind(void)
virtual void SetClean(void)
virtual void DrawRectangle(const cRect &, tColor)
virtual void Pan(const cPoint &, const cRect &Source=cRect::Null)
virtual void DrawPixel(const cPoint &, tColor)
void DrawTextInternal(const cPoint &, const char *, tColor, tColor, const cFont *, int Width=0, int Height=0, int Alignment=taDefault, bool isGridText=false)
virtual void DrawImage(const cPoint &, const cImage &)
virtual ~cOglPixmap(void)
cOglPixmap(std::shared_ptr< cOglThread >, int, const cRect &, const cRect &DrawPort=cRect::Null)
virtual void DrawSlope(const cRect &, tColor, int)
virtual void DrawText(const cPoint &, const char *, tColor, tColor, const cFont *, int Width=0, int Height=0, int Alignment=taDefault)
cOglFb * m_pFramebuffer
everything is drawn onto this framebuffer (one per pixmap)
std::shared_ptr< cOglThread > m_pOglThread
virtual void SetTile(bool)
virtual void SetDirty(bool dirty=true)
virtual void MarkViewPortDirty(const cRect &)
virtual void Scroll(const cPoint &, const cRect &Source=cRect::Null)
virtual void SetLayer(int)
virtual void Fill(tColor)
virtual void SetDrawPortPoint(const cPoint &, bool Dirty=true)
virtual void DrawBitmap(const cPoint &, const cBitmap &, tColor ColorFg=0, tColor ColorBg=0, bool Overlay=false)
virtual void Render(const cPixmap *, const cRect &, const cPoint &)
virtual void Copy(const cPixmap *, const cRect &, const cPoint &)
virtual void DrawEllipse(const cRect &, tColor, int Quadrants=0)
virtual void SetAlpha(int)
virtual void DrawScaledImage(const cPoint &, const cImage &, double FactorX=1.0f, double FactorY=1.0f, bool AntiAlias=false)
virtual void SetViewPort(const cRect &)
bool CheckCompileErrors(GLuint, bool program=false)
void SetMatrix4(const GLchar *, const glm::mat4 &)
void SetVector4f(const GLchar *, GLfloat, GLfloat, GLfloat, GLfloat)
void SetFloat(const GLchar *, GLfloat)
void SetInteger(const GLchar *, GLint)
void SetVector3f(const GLchar *, GLfloat, GLfloat, GLfloat)
bool Compile(const char *, const char *)
void SetVector2f(const GLchar *, GLfloat, GLfloat)
bool InitVertexBuffers(void)
void eglReleaseContext(void)
sOglImage m_imageCache[OGL_MAX_OSDIMAGES]
cOglThread(cCondWait *startWait, int maxCacheSize, cSoftHdDevice *device)
virtual void Action(void)
int StoreImage(const cImage &)
sOglImage * GetImageRef(int)
void DeleteVertexBuffers(void)
std::queue< cOglCmd * > m_commands
void eglAcquireContext(void)
void EnableBlending(void)
void SetShaderColor(GLint)
void SetShaderTexture(GLint)
void DisableBlending(void)
void SetVertexSubData(GLfloat *, int count=0)
void SetShaderProjectionMatrix(GLint, GLint)
void SetVertexData(GLfloat *, int count=0)
void DrawArrays(int count=0)
void ActivateShader(void)
void SetShaderAlpha(GLint)
void SetShaderBorderColor(GLint)
void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int, int)
Draw an OSD pixmap.
virtual void GetOsdSize(int &, int &, double &)
Returns the width, height and aspect ratio the OSD.
void OsdClose(void)
Close the OSD.
Logger class header file.
#define L_OPENGL_TIME_ALL
Misc function header file.
static cOglVb * VertexBuffers[vbCount]
static void ConvertColor(const GLint &colARGB, glm::vec4 &col)
static cOglShader * Shaders[stCount]
Osd class - hardware accelerated (OpenGL/ES) - header file.
#define OGL_MAX_OSDIMAGES
const struct @0 FT_Errors[]
#define OGL_CMDQUEUE_SIZE
Shader definitions for OpenGL osd class.
const char * textureFragmentShaderSwapBR
In difference to the textureFragmentShader this one does a blue/red color component swap.
const char * rectVertexShader
const char * textureFragmentShader
const char * rectFragmentShader
const char * textFragmentShader
const char * textureVertexShader
const char * textVertexShader
Device class header file.
Rendering class header file.