forked from zillevdr/vdr-plugin-softhddevice-drm
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathopenglosd.h
More file actions
857 lines (796 loc) · 22.5 KB
/
Copy pathopenglosd.h
File metadata and controls
857 lines (796 loc) · 22.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
// SPDX-License-Identifier: AGPL-3.0-or-later
/**
* @file openglosd.h
* OpenGL OSD Header File
*
* @note This file was originally authored by Stefan Braun (see README),
* but there was never set any copyright info.
*
* @copyright 2025 - 2026 by Andreas Baierl. All Rights Reserved.
*
* @license{AGPL-3.0-or-later}
*/
#ifndef __SOFTHDDEVICE_OPENGLOSD_H
#define __SOFTHDDEVICE_OPENGLOSD_H
#include <cstdio>
#include <memory>
#include <mutex>
#include <queue>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_LCD_FILTER_H
#include FT_STROKER_H
#undef __FTERRORS_H__
#define FT_ERRORDEF( e, v, s ) { e, s },
#define FT_ERROR_START_LIST {
#define FT_ERROR_END_LIST { 0, 0 } };
const struct {
int code;
const char* message;
} FT_Errors[] =
#include FT_ERRORS_H
#include <GLES2/gl2.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vdr/osd.h>
class cSoftHdDevice;
class cVideoRender;
/**
* OpenGL OSD (GPU)
*
* @ingroup osd
*/
#define BORDERCOLOR 0x00000000 ///< This is needed for the GLES2 GL_CLAMP_TO_BORDER workaround
struct sOglImage {
GLuint texture;
GLint width;
GLint height;
bool used;
};
enum eShaderType {
stRect,
stTexture,
stTextureSwapBR,
stText,
stCount
};
/**
* OpenGL OSD Vertex/Fragment Shader
*
* Represents a shader and keeps everything we need to set variable within the shader
*
* @ingroup osd
*/
class cOglShader {
public:
cOglShader(void) {};
bool Load(eShaderType);
void Use(void);
void SetFloat (const GLchar *, GLfloat);
void SetInteger (const GLchar *, GLint);
void SetVector2f (const GLchar *, GLfloat, GLfloat);
void SetVector3f (const GLchar *, GLfloat, GLfloat, GLfloat);
void SetVector4f (const GLchar *, GLfloat, GLfloat, GLfloat, GLfloat);
void SetMatrix4 (const GLchar *, const glm::mat4 &);
private:
eShaderType m_type;
GLuint m_id;
bool Compile(const char *, const char *);
bool CheckCompileErrors(GLuint, bool program = false);
};
/**
* OpenGL OSD Glyph of a Font
*
* @ingroup osd
*/
class cOglGlyph : public cListObject {
public:
cOglGlyph(FT_ULong, FT_BitmapGlyph);
virtual ~cOglGlyph();
FT_ULong CharCode(void) { return m_charCode; }
int AdvanceX(void) { return m_advanceX; }
int BearingLeft(void) const { return m_bearingLeft; }
int BearingTop(void) const { return m_bearingTop; }
int Width(void) const { return m_width; }
int Height(void) const { return m_height; }
int GetKerningCache(FT_ULong);
void SetKerningCache(FT_ULong, int);
void LoadTexture(void);
void BindTexture(void);
protected:
struct tKerning {
public:
tKerning(FT_ULong prevSym, GLfloat kerning = 0.0f) {
this->prevSym = prevSym;
this->kerning = kerning;
}
FT_ULong prevSym;
GLfloat kerning;
};
FT_ULong m_charCode;
int m_bearingLeft;
int m_bearingTop;
int m_width;
int m_height;
unsigned char *m_pBuffer;
int m_advanceX;
cVector<tKerning> m_pKerningCache;
GLuint m_texture = 0;
};
/**
* OpenGL OSD Glyph on a Texture Atlas
*
* A glyph of a font-atlas (texture-atlas) needs some more infos like offset on the texture
*
* @ingroup osd
*/
class cOglAtlasGlyph : public cOglGlyph {
public:
cOglAtlasGlyph(FT_ULong charCode, FT_BitmapGlyph ftGlyph, float offsetX, float offsetY)
: cOglGlyph(charCode, ftGlyph),
m_advanceY(ftGlyph->root.advance.y >> 16), // value in 1/2^16 pixel
m_offsetX(offsetX),
m_offsetY(offsetY) {};
int AdvanceY(void) { return m_advanceY; }
float OffsetX(void) const { return m_offsetX; }
float OffsetY(void) const { return m_offsetY; }
private:
int m_advanceY;
float m_offsetX;
float m_offsetY;
};
#define MIN_CHARCODE 32
#define MAX_CHARCODE 255
/**
* OpenGL OSD Texture Atlas for a Font
*
* Represents a texture atlas keeping a range of glyphs on one texture per font and size
* instead of having one texture per glyph. This technique makes dealing with huge
* amounts of glyphs faster, because the bottleneck (texture up-/download/binding) is
* reduced at a minimum. Its faster to deal with one single bigger texture than many
* smaller ones.
*
* The font atlas is prepared once at the time the new font or sized is accessed for the
* first time. We may have a little delay at startup, which is negligible.
*
* @ingroup osd
*/
class cOglFontAtlas {
public:
cOglFontAtlas(FT_Face, int);
virtual ~cOglFontAtlas(void);
cOglAtlasGlyph* GetGlyph(int) const;
int Height(void) const { return m_height; }
int Width(void) const { return m_width; }
void BindTexture(void);
private:
GLuint m_texture = 0;
int m_width = 0;
int m_height = 0;
cOglAtlasGlyph* m_pGlyph[MAX_CHARCODE - MIN_CHARCODE + 1];
};
/**
* OpenGL OSD Representation of a VDR Font
*
* Represents a OSD font (one per size and font family) using FreeType
*
* @ingroup osd
*/
class cOglFont : public cListObject {
public:
virtual ~cOglFont(void);
static cOglFont *Get(const char *, int);
cOglFontAtlas *Atlas(void) { return m_pAtlas; };
static void Cleanup(void);
const char *Name(void) { return *m_name; };
int Size(void) { return m_size; };
int Bottom(void) {return m_bottom; };
int Height(void) {return m_height; };
cOglGlyph* Glyph(FT_ULong) const;
int Kerning(cOglGlyph *glyph, FT_ULong prevSym) const;
private:
static bool s_initiated;
static FT_Library s_ftLib;
static cList<cOglFont> *s_pFonts;
cString m_name;
int m_size;
int m_height = 0;
int m_bottom = 0;
FT_Face m_face;
mutable cList<cOglGlyph> m_glyphCache;
cOglFontAtlas *m_pAtlas;
cOglFont(const char *, int);
static void Init(void);
};
/**
* OpenGL OSD Framebuffer/ Texture Object
*
* A framebuffer object which can be rendered onto (pixmap)
*
* @ingroup osd
*/
class cOglFb {
public:
cOglFb(GLint, GLint, GLint, GLint);
virtual ~cOglFb(void);
bool Initiated(void) { return m_initiated; }
virtual bool Init(void);
void Bind(void);
virtual void Unbind(void);
bool BindTexture(void);
void Blit(GLint, GLint, GLint, GLint);
GLint Width(void) { return m_width; };
GLint Height(void) { return m_height; };
bool Scrollable(void) { return m_scrollable; };
GLint ViewportWidth(void) { return m_viewPortWidth; };
GLint ViewportHeight(void) { return m_viewPortHeight; };
protected:
bool m_initiated = false;
GLint m_width, m_height;
private:
GLuint m_framebuffer = 0;
GLuint m_texture = 0;
GLint m_viewPortWidth, m_viewPortHeight;
bool m_scrollable = false;
};
/**
* Main Framebuffer/ Texture Object for OSD
*
* Output Framebuffer Object - holds the texture which is our "OSD output framebuffer"
*
* @ingroup osd
*/
class cOglOutputFb : public cOglFb {
public:
cOglOutputFb(GLint width, GLint height) : cOglFb(width, height, width, height) {};
virtual bool Init(void);
virtual void Unbind(void);
private:
GLuint m_framebuffer = 0;
GLuint m_texture = 0;
};
enum eVertexBufferType {
vbRect,
vbEllipse,
vbSlope,
vbTexture,
vbTextureSwapBR,
vbText,
vbCount
};
/**
* OpenGL OSD Vertex Buffers
*
* Describes and handles the OpenGL vertices for the different drawing commands
*
* @ingroup osd
*/
class cOglVb {
public:
cOglVb(int type) : m_type((eVertexBufferType)type) {};
virtual ~cOglVb(void) {};
bool Init(void);
void Bind(void);
void Unbind(void);
void ActivateShader(void);
void EnableBlending(void);
void DisableBlending(void);
void SetShaderColor(GLint);
void SetShaderBorderColor(GLint);
void SetShaderTexture(GLint);
void SetShaderAlpha(GLint);
void SetShaderProjectionMatrix(GLint, GLint);
void SetVertexSubData(GLfloat *, int count = 0);
void SetVertexData(GLfloat *, int count = 0);
void DrawArrays(int count = 0);
private:
eVertexBufferType m_type;
eShaderType m_shader;
GLuint m_vao;
GLuint m_vbo = 0;
GLuint m_positionLoc = 0;
GLuint m_texCoordsLoc = 1;
int m_sizeVertex1 = 0;
int m_sizeVertex2 = 0;
int m_numVertices = 0;
GLuint m_drawMode = 0;
};
/**
* OpenGL Hardware Command
*
* Every draw action is transposed to one of the following cOglCmd* methods,
* which are sent to the command queue, executed by cOglThread.
*
* @ingroup osd
*/
class cOglCmd {
public:
cOglCmd(cOglFb *fb)
: m_pFramebuffer(fb) {};
virtual ~cOglCmd(void) {};
virtual const char* Description(void) = 0;
virtual bool Execute(void) = 0;
virtual bool NeedsLockingAgainstStateChange(void) { return false; };
protected:
cOglFb *m_pFramebuffer;
};
/**
* OpenGL command: Init the output framebuffer
*
* @ingroup osd
*/
class cOglCmdInitOutputFb : public cOglCmd {
public:
cOglCmdInitOutputFb(cOglOutputFb *oFb)
: cOglCmd(NULL),
m_pOutputFramebuffer(oFb) {};
virtual ~cOglCmdInitOutputFb(void) {};
virtual const char* Description(void) { return "InitOutputFramebuffer"; }
virtual bool Execute(void);
private:
cOglOutputFb *m_pOutputFramebuffer;
};
/**
* OpenGL command: Init a framebuffer
*
* @ingroup osd
*/
class cOglCmdInitFb : public cOglCmd {
public:
cOglCmdInitFb(cOglFb *fb, cCondWait *wait = NULL)
: cOglCmd(fb),
m_wait(wait) {};
virtual ~cOglCmdInitFb(void) {};
virtual const char* Description(void) { return "InitFramebuffer"; }
virtual bool Execute(void);
private:
cCondWait *m_wait;
};
/**
* OpenGL command: Delete a framebuffer
*
* @ingroup osd
*/
class cOglCmdDeleteFb : public cOglCmd {
public:
cOglCmdDeleteFb(cOglFb *fb)
: cOglCmd(fb) {};
virtual ~cOglCmdDeleteFb(void) {};
virtual const char* Description(void) { return "DeleteFramebuffer"; }
virtual bool Execute(void);
};
/**
* OpenGL command: Render a framebuffer to another framebuffer
*
* @ingroup osd
*/
class cOglCmdRenderFbToBufferFb : public cOglCmd {
public:
cOglCmdRenderFbToBufferFb(cOglFb *fb, cOglFb *buffer, GLint x, GLint y, GLint transparency, GLint drawPortX, GLint drawPortY, GLint dirtyX, GLint dirtyTop, GLint dirtyWidth, GLint dirtyHeight, bool alphablending)
: cOglCmd(fb),
m_pBuffer(buffer),
m_x((GLfloat)x),
m_y((GLfloat)y),
m_drawPortX((GLfloat)drawPortX),
m_drawPortY((GLfloat)drawPortY),
m_transparency((alphablending ? transparency : ALPHA_OPAQUE)),
m_bcolor(BORDERCOLOR),
m_dirtyX(dirtyX),
m_dirtyTop(dirtyTop),
m_dirtyWidth(dirtyWidth),
m_dirtyHeight(dirtyHeight),
m_alphablending(alphablending) {};
virtual ~cOglCmdRenderFbToBufferFb(void) {};
virtual const char* Description(void) { return "Render Framebuffer to Buffer"; }
virtual bool Execute(void);
private:
cOglFb *m_pBuffer;
GLfloat m_x, m_y;
GLfloat m_drawPortX, m_drawPortY;
GLint m_transparency;
GLint m_bcolor;
GLint m_dirtyX;
GLint m_dirtyTop;
GLint m_dirtyWidth;
GLint m_dirtyHeight;
bool m_alphablending;
};
/**
* OpenGL command: Render a framebuffer to the output framebuffer
*
* @ingroup osd
*/
class cOglCmdCopyBufferToOutputFb : public cOglCmd {
public:
cOglCmdCopyBufferToOutputFb(cOglFb *fb, cOglOutputFb *oFb, GLint x, GLint y, int active, cSoftHdDevice *device)
: cOglCmd(fb),
m_pOutputFramebuffer(oFb),
m_x((GLfloat)x),
m_y((GLfloat)y),
m_borderColor(BORDERCOLOR),
m_active(active),
m_pDevice(device) {};
virtual ~cOglCmdCopyBufferToOutputFb(void) {};
virtual const char* Description(void) { return "Copy buffer to OutputFramebuffer"; }
virtual bool Execute(void);
bool NeedsLockingAgainstStateChange(void) { return true; };
private:
cOglOutputFb *m_pOutputFramebuffer;
GLfloat m_x, m_y;
GLint m_borderColor;
int m_active;
cSoftHdDevice *m_pDevice;
};
/**
* OpenGL command: Render a framebuffer into another one
*
* @ingroup osd
*/
class cOglCmdRenderFbToFb : public cOglCmd {
public:
cOglCmdRenderFbToFb(cOglFb *dstFb, cOglFb *srcFb, const cRect &src, const cPoint &dst, int alpha)
: cOglCmd(dstFb),
m_pSrcFb(srcFb),
m_srcRect(src),
m_dstPoint(dst),
m_alpha(alpha) {};
virtual ~cOglCmdRenderFbToFb(void) {};
virtual const char* Description(void) { return "Render framebuffer"; }
virtual bool Execute(void);
private:
cOglFb *m_pSrcFb;
cRect m_srcRect;
cPoint m_dstPoint;
int m_alpha;
};
/**
* OpenGL command: Fill a polygon
*
* @ingroup osd
*/
class cOglCmdFill : public cOglCmd {
public:
cOglCmdFill(cOglFb *fb, GLint color)
: cOglCmd(fb),
m_color(color) {};
virtual ~cOglCmdFill(void) {};
virtual const char* Description(void) { return "Fill"; }
virtual bool Execute(void);
private:
GLint m_color;
};
/**
* OpenGL command: Fill a framebuffer
*
* @ingroup osd
*/
class cOglCmdBufferFill : public cOglCmd {
public:
cOglCmdBufferFill(cOglFb *fb, GLint color)
: cOglCmd(fb),
m_color(color) {};
virtual ~cOglCmdBufferFill(void) {};
virtual const char* Description(void) { return "Fill Buffer "; }
virtual bool Execute(void);
private:
GLint m_color;
};
/**
* OpenGL command: Draw a rectangle
*
* @ingroup osd
*/
class cOglCmdDrawRectangle : public cOglCmd {
public:
cOglCmdDrawRectangle( cOglFb *fb, GLint x, GLint y, GLint width, GLint height, GLint color)
: cOglCmd(fb),
m_x(x),
m_y(y),
m_width(width),
m_height(height),
m_color(color) {};
virtual ~cOglCmdDrawRectangle(void) {};
virtual const char* Description(void) { return "DrawRectangle"; }
virtual bool Execute(void);
private:
GLint m_x, m_y;
GLint m_width, m_height;
GLint m_color;
};
/**
* OpenGL command: Draw an ellipse
*
* @ingroup osd
*/
class cOglCmdDrawEllipse : public cOglCmd {
public:
cOglCmdDrawEllipse( cOglFb *fb, GLint x, GLint y, GLint width, GLint height, GLint color, GLint quadrants)
: cOglCmd(fb),
m_x(x),
m_y(y),
m_width(width),
m_height(height),
m_color(color),
m_quadrants(quadrants) {};
virtual ~cOglCmdDrawEllipse(void) {};
virtual const char* Description(void) { return "DrawEllipse "; }
virtual bool Execute(void);
private:
GLint m_x, m_y;
GLint m_width, m_height;
GLint m_color;
GLint m_quadrants;
GLfloat *CreateVerticesFull(int &);
GLfloat *CreateVerticesQuadrant(int &);
GLfloat *CreateVerticesHalf(int &);
};
/**
* OpenGL command: Draw a slope
*
* @ingroup osd
*/
class cOglCmdDrawSlope : public cOglCmd {
public:
cOglCmdDrawSlope( cOglFb *fb, GLint x, GLint y, GLint width, GLint height, GLint color, GLint type)
: cOglCmd(fb),
m_x(x),
m_y(y),
m_width(width),
m_height(height),
m_color(color),
m_type(type) {};
virtual ~cOglCmdDrawSlope(void) {};
virtual const char* Description(void) { return "DrawSlope "; }
virtual bool Execute(void);
private:
GLint m_x, m_y;
GLint m_width, m_height;
GLint m_color;
GLint m_type;
};
/**
* OpenGL command: Draw a text
*
* @ingroup osd
*/
class cOglCmdDrawText : public cOglCmd {
public:
cOglCmdDrawText(cOglFb *fb, GLint x, GLint y, unsigned int *symbols, GLint limitX, const char *name, int fontSize, tColor colorText, int length)
: cOglCmd(fb),
m_x(x),
m_y(y),
m_limitX(limitX),
m_colorText(colorText),
m_length(length),
m_fontName(name),
m_fontSize(fontSize),
m_pSymbols(symbols) {};
virtual ~cOglCmdDrawText(void) { free(m_pSymbols); };
virtual const char* Description(void) { return "DrawText "; }
virtual bool Execute(void);
private:
GLint m_x, m_y;
GLint m_limitX;
GLint m_colorText;
int m_length;
cString m_fontName;
int m_fontSize;
unsigned int *m_pSymbols;
};
/**
* OpenGL command: Draw an image
*
* @ingroup osd
*/
class cOglCmdDrawImage : public cOglCmd {
public:
cOglCmdDrawImage(cOglFb *fb, tColor *argb, GLint width, GLint height, GLint x, GLint y, bool overlay = true, double scaleX = 1.0f, double scaleY = 1.0f)
: cOglCmd(fb),
m_argb(argb),
m_x(x),
m_y(y),
m_width(width),
m_height(height),
m_overlay(overlay),
m_scaleX(scaleX),
m_scaleY(scaleY),
m_borderColor(BORDERCOLOR) {};
virtual ~cOglCmdDrawImage(void) { free(m_argb); };
virtual const char* Description(void) { return "Draw Image"; }
virtual bool Execute(void);
private:
tColor *m_argb;
GLint m_x, m_y, m_width, m_height;
bool m_overlay;
GLfloat m_scaleX, m_scaleY;
GLint m_borderColor;
};
/**
* OpenGL command: Draw a texture
*
* @ingroup osd
*/
class cOglCmdDrawTexture : public cOglCmd {
public:
cOglCmdDrawTexture(cOglFb *fb, sOglImage *imageRef, GLint x, GLint y, double scaleX = 1.0f, double scaleY = 1.0f)
: cOglCmd(fb),
m_pImageRef(imageRef),
m_x(x),
m_y(y),
m_scaleX(scaleX),
m_scaleY(scaleY),
m_borderColor(BORDERCOLOR) {};
virtual ~cOglCmdDrawTexture(void) {};
virtual const char* Description(void) { return "Draw Texture"; }
virtual bool Execute(void);
private:
sOglImage *m_pImageRef;
GLint m_x, m_y;
GLfloat m_scaleX, m_scaleY;
GLint m_borderColor;
};
/**
* OpenGL command: Store image in the cache
*
* @ingroup osd
*/
class cOglCmdStoreImage : public cOglCmd {
public:
cOglCmdStoreImage(sOglImage *imageRef, tColor *argb)
: cOglCmd(NULL),
m_pImageRef(imageRef),
m_pData(argb) {};
virtual ~cOglCmdStoreImage(void) { free(m_pData); };
virtual const char* Description(void) { return "Store Image"; }
virtual bool Execute(void);
private:
sOglImage *m_pImageRef;
tColor *m_pData;
};
/**
* OpenGL command: Drop image from cache
*
* @ingroup osd
*/
class cOglCmdDropImage : public cOglCmd {
public:
cOglCmdDropImage(sOglImage *imageRef, cCondWait *wait)
: cOglCmd(NULL),
m_pImageRef(imageRef),
m_pWait(wait) {};
virtual ~cOglCmdDropImage(void) {};
virtual const char* Description(void) { return "Drop Image"; }
virtual bool Execute(void);
private:
sOglImage *m_pImageRef;
cCondWait *m_pWait;
};
#define OGL_MAX_OSDIMAGES 512
#define OGL_CMDQUEUE_SIZE 200
/**
* OpenGL Commands Processing Thread
*
* Continuosly executes OpenGL commands
*
* Every OSD draw or flush which is invoked by VDR is transposed into an
* OpenGL command.
* cOglThread holds a fifo-queue of these commands. It continuosly checks
* for commands on the queue, pops them and sends them to the hardware.
*
* On startup it initiates all necessary OpenGL bits.
*
* @ingroup osd
*/
class cOglThread : public cThread {
public:
cOglThread(cCondWait *startWait, int maxCacheSize, cSoftHdDevice *device);
virtual ~cOglThread(void) {};
void RequestStop(void);
void Stop(void);
void DoCmd(cOglCmd*);
int StoreImage(const cImage &);
void DropImageData(int);
sOglImage *GetImageRef(int);
int MaxTextureSize(void) { return m_maxTextureSize; };
void LockOutputFb(void) { m_mutex.lock(); };
void UnlockOutputFb(void) { m_mutex.unlock(); };
protected:
virtual void Action(void);
private:
cCondWait *m_startWait;
cCondWait m_wait;
bool m_stalled = false;
std::queue<cOglCmd*> m_commands;
GLint m_maxTextureSize = 0;
sOglImage m_imageCache[OGL_MAX_OSDIMAGES];
long m_memCached = 0;
long m_maxCacheSize;
cVideoRender *m_pRender;
std::mutex m_mutex;
bool InitOpenGL(void);
bool InitShaders(void);
void DeleteShaders(void);
bool InitVertexBuffers(void);
void DeleteVertexBuffers(void);
void Cleanup(void);
void CleanupImageCache(void);
int GetFreeSlot(void);
void ClearSlot(int slot);
void eglAcquireContext(void);
};
/**
* OpenGL Implementation of a cPixmap
*
* @ingroup osd
*/
class cOglPixmap : public cPixmap {
public:
cOglPixmap(std::shared_ptr<cOglThread>, int, const cRect &, const cRect &DrawPort = cRect::Null);
virtual ~cOglPixmap(void);
cOglFb *Framebuffer(void) const { return m_pFramebuffer; };
int X(void) { return ViewPort().X(); };
int Y(void) { return ViewPort().Y(); };
virtual bool IsDirty(void) { return m_dirty; }
virtual void SetDirty(bool dirty = true) { m_dirty = dirty; }
virtual void SetLayer(int);
virtual void SetAlpha(int);
virtual void SetTile(bool);
virtual void SetViewPort(const cRect &);
virtual void SetDrawPortPoint(const cPoint &, bool Dirty = true);
virtual void Clear(void);
virtual void Fill(tColor);
virtual void DrawImage(const cPoint &, const cImage &);
virtual void DrawImage(const cPoint &, int);
virtual void DrawScaledImage(const cPoint &, const cImage &, double FactorX = 1.0f, double FactorY = 1.0f, bool AntiAlias = false);
virtual void DrawScaledImage(const cPoint &, int, double FactorX = 1.0f, double FactorY = 1.0f, bool AntiAlias = false);
virtual void DrawPixel(const cPoint &, tColor);
virtual void DrawBitmap(const cPoint &, const cBitmap &, tColor ColorFg = 0, tColor ColorBg = 0, bool Overlay = false);
virtual void DrawText(const cPoint &, const char *, tColor, tColor, const cFont *, int Width = 0, int Height = 0, int Alignment = taDefault);
virtual void DrawRectangle(const cRect &, tColor);
virtual void DrawEllipse(const cRect &, tColor, int Quadrants = 0);
virtual void DrawSlope(const cRect &, tColor, int);
virtual void Render(const cPixmap *, const cRect &, const cPoint &);
virtual void Copy(const cPixmap *, const cRect &, const cPoint &);
virtual void Scroll(const cPoint &, const cRect &Source = cRect::Null);
virtual void Pan(const cPoint &, const cRect &Source = cRect::Null);
virtual void MarkViewPortDirty(const cRect &);
virtual void SetClean(void);
private:
cOglFb *m_pFramebuffer; ///< everything is drawn onto this framebuffer (one per pixmap)
std::shared_ptr<cOglThread> m_pOglThread;
bool m_dirty = true; ///< true, if there was draw activity on the pixmap
#ifdef GRIDPOINTS
cFont *m_pTinyfont;
void DrawGridRect(const cRect &, int, int, tColor, tColor, const cFont *);
void DrawGridText(const cPoint &, const char *, tColor, tColor, const cFont *, int Width = 0, int Height = 0, int Alignment = taDefault);
#endif
void DrawTextInternal(const cPoint &, const char *, tColor, tColor, const cFont *, int Width = 0, int Height = 0, int Alignment = taDefault, bool isGridText = false);
void RenderPixmapInternal(const cPixmap *, const cRect &, const cPoint &, bool);
};
/**
* OpenGL OSD Implementation (GPU accelerated)
*
* @ingroup osd
*/
class cOglOsd : public cOsd {
public:
cOglOsd(int, int, uint, std::shared_ptr<cOglThread>, cSoftHdDevice *);
virtual ~cOglOsd();
virtual eOsdError SetAreas(const tArea *, int);
virtual cPixmap *CreatePixmap(int, const cRect &, const cRect &DrawPort = cRect::Null);
virtual void DestroyPixmap(cPixmap *);
virtual void Flush(void);
virtual const cSize &MaxPixmapSize(void) const { return m_maxPixmapSize; };
virtual void DrawScaledBitmap(int, int, const cBitmap &, double, double, bool AntiAlias = false);
static cOglOutputFb *OutputFramebuffer; ///< main OSD output framebuffer - this keeps our finished "OSD" (one per OSD)
private:
cOglFb *m_pBufferFramebuffer = nullptr; ///< all pixmaps are composed onto this framebuffer after each other,
///< before this one is blit onto the OSD output framebuffer
std::shared_ptr<cOglThread> m_pOglThread; ///< pointer to thread, which executes the commands
cVector<cOglPixmap *> m_pOglPixmaps; ///< array of pixmaps
bool m_isSubtitleOsd; ///< true, if this is a subtitle osd
cSize m_maxPixmapSize; ///< maximum allowed size of a pixmap (depends on the maximum OpenGL texture size)
cRect m_pDirtyViewport; ///< the dirty viewport
cSoftHdDevice *m_pDevice; ///< pointer to cSofthdDevice
};
#endif