3 * (c) 2016 K.Ohta <whatisthis.sowhat@gmail.com>
5 * Renderer with OpenGL v3.0 (extend from renderer with OpenGL v2.0).
7 * Jan 22, 2016 : Initial.
10 #include "osd_types.h"
11 #include "qt_gldraw.h"
12 #include "qt_glpack.h"
13 #include "qt_glutil_gl4_5.h"
14 #include "csp_logger.h"
15 #include "menu_flags.h"
17 #include <QOpenGLFunctions>
18 #include <QOpenGLTexture>
20 #include <QImageReader>
22 #include <QOpenGLPixelTransferOptions>
23 #include <QOpenGLVertexArrayObject>
24 #include <QOpenGLShaderProgram>
25 #include <QOpenGLBuffer>
27 #include <QOpenGLContext>
28 #include <QOpenGLFramebufferObject>
29 #include <QOpenGLFramebufferObjectFormat>
30 #include <QOpenGLPixelTransferOptions>
41 #include <QOpenGLFunctions_4_5_Core>
43 //extern USING_FLAGS *using_flags;
45 GLDraw_4_5::GLDraw_4_5(GLDrawClass *parent, USING_FLAGS *p, CSP_Logger *logger, EMU *emu) : GLDraw_Tmpl(parent, p, logger, emu)
56 for(int i = 0; i < 32; i++) {
57 led_pass_vao[i] = NULL;
58 led_pass_vbuffer[i] = NULL;
59 osd_pass_vao[i] = NULL;
60 osd_pass_vbuffer[i] = NULL;
62 grids_horizonal_buffer = NULL;
63 grids_horizonal_vertex = NULL;
65 grids_vertical_buffer = NULL;
66 grids_vertical_vertex = NULL;
68 #if defined(__LITTLE_ENDIAN__)
69 swap_byteorder = true;
71 swap_byteorder = false;
75 main_texture_buffer = 0;
76 map_base_address = NULL;
77 main_mutex = new QMutex();
78 main_texture_ready = false;
81 GLDraw_4_5::~GLDraw_4_5()
84 if(main_pass != NULL) delete main_pass;
85 if(std_pass != NULL) delete std_pass;
86 if(ntsc_pass1 != NULL) delete ntsc_pass1;
87 if(ntsc_pass2 != NULL) delete ntsc_pass2;
88 if(led_pass != NULL) delete led_pass;
89 for(int i = 0; i < 32; i++) {
90 if(led_pass_vao[i] != NULL) delete led_pass_vao[i];
91 if(led_pass_vbuffer[i] != NULL) delete led_pass_vbuffer[i];
92 if(osd_pass_vao[i] != NULL) delete osd_pass_vao[i];
93 if(osd_pass_vbuffer[i] != NULL) delete osd_pass_vbuffer[i];
96 if(grids_horizonal_buffer != NULL) {
97 if(grids_horizonal_buffer->isCreated()) grids_horizonal_buffer->destroy();
99 if(grids_horizonal_vertex != NULL) {
100 if(grids_horizonal_vertex->isCreated()) grids_horizonal_vertex->destroy();
102 if(grids_vertical_buffer != NULL) {
103 if(grids_vertical_buffer->isCreated()) grids_vertical_buffer->destroy();
105 if(grids_horizonal_vertex != NULL) {
106 if(grids_vertical_vertex->isCreated()) grids_vertical_vertex->destroy();
110 QOpenGLTexture *GLDraw_4_5::createMainTexture(QImage *img)
117 w = using_flags->get_real_screen_width();
118 h = using_flags->get_real_screen_height();
123 QImage im(w, h, QImage::Format_RGBA8888);
129 //tx->setFormat(QOpenGLTexture::RGBA8_UNorm);
131 if(main_texture_buffer != 0) {
133 main_texture_ready = false;
134 this->unmap_vram_texture();
135 map_base_address = NULL;
136 extfunc->glDeleteBuffers(1, &main_texture_buffer);
137 main_texture_buffer = 0;
139 extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
140 extfunc->glDeleteSync(sync_fence);
141 sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
142 main_mutex->unlock();
146 extfunc->glGenBuffers(1, &main_texture_buffer);
147 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
148 //extfunc->glBufferData(GL_PIXEL_UNPACK_BUFFER, w * h * sizeof(uint32_t), ip->constBits(), GL_DYNAMIC_COPY);
149 //extfunc->glBufferStorage(GL_PIXEL_UNPACK_BUFFER, w * h * sizeof(uint32_t), ip->constBits(), GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
150 extfunc->glBufferStorage(GL_PIXEL_UNPACK_BUFFER, w * h * sizeof(uint32_t), ip->constBits(), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
151 tx = new QOpenGLTexture(QOpenGLTexture::Target2D);
152 tx->setFormat(QOpenGLTexture::RGBA8_UNorm);
153 tx->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Nearest);
154 tx->setWrapMode(QOpenGLTexture::ClampToEdge);
155 tx->setData(*ip, QOpenGLTexture::DontGenerateMipMaps);
158 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
160 extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
161 extfunc->glDeleteSync(sync_fence);
162 sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
164 if(map_vram_texture()) {
165 main_texture_ready = true;
169 main_mutex->unlock();
176 void GLDraw_4_5::initBitmapVertex(void)
178 if(using_flags->is_use_one_board_computer()) {
179 vertexBitmap[0].x = -1.0f;
180 vertexBitmap[0].y = -1.0f;
181 vertexBitmap[0].z = 0.5f;
182 vertexBitmap[0].s = 0.0f;
183 vertexBitmap[0].t = 1.0f;
185 vertexBitmap[1].x = +1.0f;
186 vertexBitmap[1].y = -1.0f;
187 vertexBitmap[1].z = 0.5f;
188 vertexBitmap[1].s = 1.0f;
189 vertexBitmap[1].t = 1.0f;
191 vertexBitmap[2].x = +1.0f;
192 vertexBitmap[2].y = +1.0f;
193 vertexBitmap[2].z = 0.5f;
194 vertexBitmap[2].s = 1.0f;
195 vertexBitmap[2].t = 0.0f;
197 vertexBitmap[3].x = -1.0f;
198 vertexBitmap[3].y = +1.0f;
199 vertexBitmap[3].z = 0.5f;
200 vertexBitmap[3].s = 0.0f;
201 vertexBitmap[3].t = 0.0f;
206 void GLDraw_4_5::initFBO(void)
208 glHorizGrids = (GLfloat *)malloc(sizeof(float) * (using_flags->get_real_screen_height() + 2) * 6);
210 if(glHorizGrids != NULL) {
211 doSetGridsHorizonal(using_flags->get_real_screen_height(), true);
213 glVertGrids = (GLfloat *)malloc(sizeof(float) * (using_flags->get_real_screen_width() + 2) * 6);
214 if(glVertGrids != NULL) {
215 doSetGridsVertical(using_flags->get_real_screen_width(), true);
217 if(using_flags->get_max_button() > 0) {
221 extfunc->glClearColor(0.0, 0.0, 0.0, 1.0);
223 sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
226 void GLDraw_4_5::setNormalVAO(QOpenGLShaderProgram *prg,
227 QOpenGLVertexArrayObject *vp,
229 VertexTexCoord_t *tp,
232 int vertex_loc = prg->attributeLocation("vertex");
233 int texcoord_loc = prg->attributeLocation("texcoord");
240 bp->write(0, tp, sizeof(VertexTexCoord_t) * size);
242 prg->setAttributeBuffer(vertex_loc, GL_FLOAT, 0, 3, sizeof(VertexTexCoord_t));
243 prg->setAttributeBuffer(texcoord_loc, GL_FLOAT, 3 * sizeof(GLfloat), 2, sizeof(VertexTexCoord_t));
244 prg->setUniformValue("a_texture", 0);
246 extfunc->glVertexAttribPointer(vertex_loc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTexCoord_t), 0);
247 extfunc->glVertexAttribPointer(texcoord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTexCoord_t),
248 (char *)NULL + 3 * sizeof(GLfloat));
251 prg->enableAttributeArray(vertex_loc);
252 prg->enableAttributeArray(texcoord_loc);
255 void GLDraw_4_5::initGLObjects()
257 extfunc = new QOpenGLFunctions_4_5_Core();
258 extfunc->initializeOpenGLFunctions();
259 extfunc->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texture_max_size);
262 void GLDraw_4_5::initPackedGLObject(GLScreenPack **p,
263 int _width, int _height,
264 const QString vertex_shader, const QString fragment_shader,
265 const QString _name, bool req_float, bool req_highp)
270 pp = new GLScreenPack(_width, _height, _name, p_wid, req_float, req_highp);
273 pp->initialize(_width, _height, vertex_shader, fragment_shader);
274 s = pp->getShaderLog();
276 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "In shader of %s ", _name.toLocal8Bit().constData());
277 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "Vertex: %s ", vertex_shader.toLocal8Bit().constData());
278 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "Fragment: %s ", fragment_shader.toLocal8Bit().constData());
279 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "%s", s.toLocal8Bit().constData());
283 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "In shader of %s ", _name.toLocal8Bit().constData());
284 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "Vertex: %s ", vertex_shader.toLocal8Bit().constData());
285 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "Fragment: %s ", fragment_shader.toLocal8Bit().constData());
286 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_GL_SHADER, "%s", s.toLocal8Bit().constData());
291 QOpenGLContext *context = QOpenGLContext::currentContext();
292 gl_major_version = context->format().version().first;
293 gl_minor_version = context->format().version().second;
299 bool GLDraw_4_5::initGridShaders(const QString vertex_fixed, const QString vertex_rotate, const QString fragment)
301 QOpenGLContext *context = QOpenGLContext::currentContext();
302 QPair<int, int> _version = QOpenGLVersionProfile(context->format()).version();
303 QString versionext = QString::fromUtf8("");
304 if(((_version.first == 4) && (_version.second >= 3)) || (_version.first >= 5)) {
305 versionext = QString::fromUtf8("#version 430 core \n"); // OK?
306 } else if((_version.first == 4)) {
307 versionext = QString::fromUtf8("#version 400 core \n");
308 } else { // Require GLVersion >= 3.2
309 versionext = QString::fromUtf8("#version 150 \n");
313 grids_shader = new QOpenGLShaderProgram(p_wid);
314 if(grids_shader == NULL) return false;
316 QFile vertex_src(vertex_rotate);
317 if (vertex_src.open(QIODevice::ReadOnly | QIODevice::Text)) {
318 QString srcs = versionext;
319 srcs = srcs + QString::fromUtf8(vertex_src.readAll());
320 f = grids_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, srcs);
326 QFile fragment_src(fragment);
327 if ((fragment_src.open(QIODevice::ReadOnly | QIODevice::Text)) && (f)){
329 QString _ext = QString::fromUtf8("");;
331 _src = QString::fromUtf8(fragment_src.readAll());
332 f &= grids_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, _ext + _src);
333 fragment_src.close();
338 f &= grids_shader->link();
342 bool GLDraw_4_5::initGridVertexObject(QOpenGLBuffer **vbo, QOpenGLVertexArrayObject **vao, int alloc_size)
344 QOpenGLBuffer *bp = NULL;
345 QOpenGLVertexArrayObject *ap = NULL;
348 *vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
353 bp->allocate(alloc_size * sizeof(GLfloat) * 3 * 2);
363 *vao = new QOpenGLVertexArrayObject;
380 void GLDraw_4_5::initLocalGLObjects(void)
383 int _width = using_flags->get_screen_width();
384 int _height = using_flags->get_screen_height();
386 if(((int)(_width * 3.5)) <= texture_max_size) {
387 _width = (int)(_width * 3.5);
388 low_resolution_screen = true;
392 p_wid->makeCurrent();
394 vertexFormat[0].x = -1.0f;
395 vertexFormat[0].y = -1.0f;
396 vertexFormat[0].z = -0.9f;
397 vertexFormat[0].s = 0.0f;
398 vertexFormat[0].t = 1.0f;
400 vertexFormat[1].x = +1.0f;
401 vertexFormat[1].y = -1.0f;
402 vertexFormat[1].z = -0.9f;
403 vertexFormat[1].s = 1.0f;
404 vertexFormat[1].t = 1.0f;
406 vertexFormat[2].x = +1.0f;
407 vertexFormat[2].y = +1.0f;
408 vertexFormat[2].z = -0.9f;
409 vertexFormat[2].s = 1.0f;
410 vertexFormat[2].t = 0.0f;
412 vertexFormat[3].x = -1.0f;
413 vertexFormat[3].y = +1.0f;
414 vertexFormat[3].z = -0.9f;
415 vertexFormat[3].s = 0.0f;
416 vertexFormat[3].t = 0.0f;
418 if(using_flags->is_use_one_board_computer() || (using_flags->get_max_button() > 0)) {
419 initPackedGLObject(&main_pass,
420 using_flags->get_screen_width() * 2, using_flags->get_screen_height() * 2,
421 ":/gl4_5/vertex_shader.glsl" , ":/gl4_5/chromakey_fragment_shader2.glsl",
422 "Main Shader", true);
424 initPackedGLObject(&main_pass,
425 using_flags->get_screen_width() * 2, using_flags->get_screen_height() * 2,
426 ":/gl4_5/vertex_shader.glsl" , ":/gl4_5/fragment_shader.glsl",
427 "Main Shader", true);
429 if(main_pass != NULL) {
430 setNormalVAO(main_pass->getShader(), main_pass->getVAO(),
431 main_pass->getVertexBuffer(),
435 initPackedGLObject(&std_pass,
436 using_flags->get_screen_width(), using_flags->get_screen_height(),
437 ":/gl4_5/vertex_shader.glsl" , ":/gl4_5/chromakey_fragment_shader.glsl",
438 "Standard Shader", true);
440 initPackedGLObject(&led_pass,
442 ":/gl4_5/led_vertex_shader.glsl" , ":/gl4_5/led_fragment_shader.glsl",
444 for(int i = 0; i < 32; i++) {
445 led_pass_vao[i] = new QOpenGLVertexArrayObject;
446 led_pass_vbuffer[i] = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
447 if(led_pass_vao[i]->create()) {
448 if(led_pass_vbuffer[i]->create()) {
449 led_pass_vbuffer[i]->setUsagePattern(QOpenGLBuffer::DynamicDraw);
450 led_pass_vao[i]->bind();
451 led_pass_vbuffer[i]->bind();
452 led_pass_vbuffer[i]->allocate(sizeof(VertexTexCoord_t) * 4);
453 led_pass_vbuffer[i]->release();
454 led_pass_vao[i]->release();
459 initPackedGLObject(&osd_pass,
461 ":/gl4_5/vertex_shader.glsl" , ":/gl4_5/icon_fragment_shader.glsl",
463 for(int i = 0; i < 32; i++) {
464 osd_pass_vao[i] = new QOpenGLVertexArrayObject;
465 osd_pass_vbuffer[i] = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
466 if(osd_pass_vao[i]->create()) {
467 if(osd_pass_vbuffer[i]->create()) {
468 osd_pass_vbuffer[i]->setUsagePattern(QOpenGLBuffer::DynamicDraw);
469 osd_pass_vao[i]->bind();
470 osd_pass_vbuffer[i]->bind();
471 osd_pass_vbuffer[i]->allocate(sizeof(VertexTexCoord_t) * 4);
472 osd_pass_vbuffer[i]->release();
473 osd_pass_vao[i]->release();
480 initPackedGLObject(&ntsc_pass1,
481 // using_flags->get_screen_width() * 2, using_flags->get_screen_height() * 2,
483 ":/gl4_5/vertex_shader.glsl" , ":/gl4_5/ntsc_pass1.glsl",
484 "NTSC Shader Pass1", true, true);
485 initPackedGLObject(&ntsc_pass2,
486 using_flags->get_screen_width() * 2, using_flags->get_screen_height() * 2,
488 ":/gl4_5/vertex_shader.glsl" , ":/gl4_5/ntsc_pass2.glsl",
489 "NTSC Shader Pass2", true, true);
490 if(!(((gl_major_version >= 3) && (gl_minor_version >= 1)) || (gl_major_version >= 4))){
492 QOpenGLShaderProgram *shader = ntsc_pass2->getShader();
494 ii = shader->uniformLocation("luma_filter");
496 shader->setUniformValueArray(ii, luma_filter, 24 + 1, 1);
498 ii = shader->uniformLocation("chroma_filter");
500 shader->setUniformValueArray(ii, chroma_filter, 24 + 1, 1);
506 if(using_flags->is_use_one_board_computer()) {
508 initPackedGLObject(&bitmap_block,
509 _width * 2, _height * 2,
510 ":/gl4_5/vertex_shader.glsl", ":/gl4_5/normal_fragment_shader.glsl",
511 "Background Bitmap Shader", true);
512 if(bitmap_block != NULL) {
513 setNormalVAO(bitmap_block->getShader(), bitmap_block->getVAO(),
514 bitmap_block->getVertexBuffer(),
519 initGridShaders(":/gl4_5/grids_vertex_shader_fixed.glsl", ":/gl4_5/grids_vertex_shader.glsl", ":/gl4_5/grids_fragment_shader.glsl");
521 initGridVertexObject(&grids_horizonal_buffer, &grids_horizonal_vertex, using_flags->get_real_screen_height() + 3);
522 doSetGridsHorizonal(using_flags->get_real_screen_height(), true);
524 initGridVertexObject(&grids_vertical_buffer, &grids_vertical_vertex, using_flags->get_real_screen_width() + 3);
525 doSetGridsVertical(using_flags->get_real_screen_width(), true);
527 do_set_texture_size(NULL, -1, -1);
528 p_wid->doneCurrent();
531 void GLDraw_4_5::updateGridsVAO(QOpenGLBuffer *bp,
532 QOpenGLVertexArrayObject *vp,
538 if((bp != NULL) && (vp != NULL)) {
539 if(bp->isCreated()) {
540 if(bp->size() < (int)((number + 1) * sizeof(GLfloat) * 3 * 2)) {
552 bp->allocate((number + 1) * sizeof(GLfloat) * 3 * 2);
555 bp->write(0, tp, number * sizeof(GLfloat) * 3 * 2);
562 void GLDraw_4_5::drawGrids(void)
564 gl_grid_horiz = p_config->opengl_scanline_horiz;
565 gl_grid_vert = p_config->opengl_scanline_vert;
566 if(gl_grid_horiz && (vert_lines > 0)) {
567 drawGridsHorizonal();
569 if(using_flags->is_use_vertical_pixel_lines()) {
570 if(gl_grid_vert && (horiz_pixels > 0)) {
576 void GLDraw_4_5::drawGridsMain(QOpenGLShaderProgram *prg,
578 QOpenGLVertexArrayObject *vp,
583 if(number <= 0) return;
584 extfunc->glDisable(GL_DEPTH_TEST);
585 extfunc->glDisable(GL_BLEND);
587 if((bp == NULL) || (vp == NULL) || (prg == NULL)) return;
588 if((!bp->isCreated()) || (!vp->isCreated()) || (!prg->isLinked())) return;
594 switch(p_config->rotate_type) {
596 rot = QMatrix2x2(rot0);
599 rot = QMatrix2x2(rot90);
602 rot = QMatrix2x2(rot180);
605 rot = QMatrix2x2(rot270);
608 rot = QMatrix2x2(rot0);
611 prg->setUniformValue("rotate_mat", rot);
612 prg->setUniformValue("color", color);
613 prg->enableAttributeArray("vertex");
614 int vertex_loc = prg->attributeLocation("vertex");
616 extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
617 extfunc->glVertexAttribPointer(vertex_loc, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
618 extfunc->glEnableVertexAttribArray(vertex_loc);
620 extfunc->glLineWidth(lineWidth);
621 extfunc->glDrawArrays(GL_LINES, 0, (number + 1) * 2);
628 void GLDraw_4_5::doSetGridsVertical(int pixels, bool force)
630 GLDraw_Tmpl::doSetGridsVertical(pixels, force);
631 updateGridsVAO(grids_vertical_buffer,
632 grids_vertical_vertex,
637 void GLDraw_4_5::doSetGridsHorizonal(int lines, bool force)
639 if((lines == vert_lines) && !force) return;
640 GLDraw_Tmpl::doSetGridsHorizonal(lines, force);
642 updateGridsVAO(grids_horizonal_buffer,
643 grids_horizonal_vertex,
648 void GLDraw_4_5::drawGridsHorizonal(void)
650 QVector4D c= QVector4D(0.0f, 0.0f, 0.0f, 1.0f);
651 drawGridsMain(grids_shader,
652 grids_horizonal_buffer,
653 grids_horizonal_vertex,
659 void GLDraw_4_5::drawGridsVertical(void)
661 QVector4D c= QVector4D(0.0f, 0.0f, 0.0f, 1.0f);
662 drawGridsMain(grids_shader,
663 grids_vertical_buffer,
664 grids_vertical_vertex,
670 void GLDraw_4_5::renderToTmpFrameBuffer_nPass(GLuint src_texture,
673 GLScreenPack *renderObject,
679 QOpenGLShaderProgram *shader = renderObject->getShader();
683 extfunc->glClearColor(0.0, 0.0, 0.0, 1.0);
684 extfunc->glClearDepthf(1.0f);
685 extfunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
687 if((src_texture != 0) && (shader != NULL)) {
689 //ortho.ortho(0.0f, (float)dst_w, 0.0f, (float)dst_h, -1.0, 1.0);
690 ortho.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
693 renderObject->bind();
694 extfunc->glViewport(0, 0, dst_w, dst_h);
695 //extfunc->glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
696 extfunc->glActiveTexture(GL_TEXTURE0);
697 extfunc->glBindTexture(GL_TEXTURE_2D, src_texture);
698 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
699 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
700 //extfunc->glColor4f(1.0, 1.0, 1.0, 1.0);
701 shader->setUniformValue("a_texture", 0);
702 shader->setUniformValue("v_ortho", ortho);
703 //shader->setUniformValue("a_texture", src_texture);
705 ii = shader->uniformLocation("source_size");
707 QVector4D source_size = QVector4D((float)src_w, (float)src_h, 0, 0);
708 shader->setUniformValue(ii, source_size);
710 ii = shader->uniformLocation("target_size");
712 QVector4D target_size = QVector4D((float)dst_w, (float)dst_h, 0, 0);
713 shader->setUniformValue(ii, target_size);
715 ii = shader->uniformLocation("phase");
717 ringing_phase = ringing_phase + 0.093;
718 if(ringing_phase > 1.0) ringing_phase = ringing_phase - 1.0;
719 shader->setUniformValue(ii, ringing_phase);
723 * Note : Not rotate within renderer.
726 switch(p_config->rotate_type) {
728 rot = QMatrix2x2(rot0);
731 rot = QMatrix2x2(rot90);
734 rot = QMatrix2x2(rot180);
737 rot = QMatrix2x2(rot270);
740 rot = QMatrix2x2(rot0);
744 rot = QMatrix2x2(rot0);
745 shader->setUniformValue("rotate_mat", rot);
746 //if(!(((gl_major_version >= 3) && (gl_minor_version >= 1)) || (gl_major_version >= 4))){
747 //ii = shader->uniformLocation("luma_filter");
749 // shader->setUniformValueArray(ii, luma_filter, 24 + 1, 1);
751 //ii = shader->uniformLocation("chroma_filter");
753 // shader->setUniformValueArray(ii, chroma_filter, 24 + 1, 1);
758 QVector4D c(fBrightR, fBrightG, fBrightB, 1.0);
759 QVector3D chromakey(0.0, 0.0, 0.0);
761 ii = shader->uniformLocation("color");
763 shader->setUniformValue(ii, c);
765 ii = shader->uniformLocation("do_chromakey");
769 ij = shader->uniformLocation("chromakey");
771 shader->setUniformValue(ij, chromakey);
773 shader->setUniformValue(ii, GL_TRUE);
775 shader->setUniformValue(ii, GL_FALSE);
780 shader->enableAttributeArray("texcoord");
781 shader->enableAttributeArray("vertex");
783 int vertex_loc = shader->attributeLocation("vertex");
784 int texcoord_loc = shader->attributeLocation("texcoord");
785 shader->setAttributeBuffer(vertex_loc, GL_FLOAT, 0, 3, sizeof(VertexTexCoord_t));
786 shader->setAttributeBuffer(texcoord_loc, GL_FLOAT, 3 * sizeof(GLfloat), 2, sizeof(VertexTexCoord_t));
787 extfunc->glEnableVertexAttribArray(vertex_loc);
788 extfunc->glEnableVertexAttribArray(texcoord_loc);
790 extfunc->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
792 //extfunc->glViewport(0, 0, dst_w, dst_h);
793 //extfunc->glOrtho(0.0f, (float)dst_w, 0.0f, (float)dst_h, -1.0, 1.0);
794 renderObject->release();
795 extfunc->glBindTexture(GL_TEXTURE_2D, 0);
801 void GLDraw_4_5::uploadMainTexture(QImage *p, bool use_chromakey, bool was_mapped)
804 redraw_required = true;
805 //if(p == NULL) return;
806 //redraw_required = true;
808 if(uVramTextureID == NULL) {
809 uVramTextureID = createMainTexture(p);
811 // Upload to main texture
814 if(map_base_address == NULL) {
815 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
816 uint32_t* pp = (uint32_t *)(extfunc->glMapNamedBufferRange(main_texture_buffer, 0, pixel_width * pixel_height * sizeof(scrntype_t), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT));
817 //uint32_t *pp = (uint32_t *)(extfunc->glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY));
819 int hh = (pixel_height < p->height()) ? pixel_height : p->height();
820 for(int y = 0; y < hh; y++) {
821 memcpy(&(pp[y * pixel_width]), p->scanLine(y), p->width() * sizeof(uint32_t));
824 extfunc->glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
825 //extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
827 //extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
828 extfunc->glBindTexture(GL_TEXTURE_2D, uVramTextureID->textureId());
829 //extfunc->glActiveTexture(GL_TEXTURE0);
830 extfunc->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, p->width(), p->height(), GL_RGBA, GL_UNSIGNED_BYTE, 0);
831 extfunc->glBindTexture(GL_TEXTURE_2D, 0);
832 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
836 extfunc->glFlushMappedBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, pixel_width *pixel_height * sizeof(scrntype_t));
837 extfunc->glWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
838 extfunc->glDeleteSync(sync_fence);
839 sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
841 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
842 extfunc->glBindTexture(GL_TEXTURE_2D, uVramTextureID->textureId());
843 //extfunc->glActiveTexture(GL_TEXTURE0);
844 extfunc->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixel_width, pixel_height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
845 extfunc->glBindTexture(GL_TEXTURE_2D, 0);
846 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
848 //extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
849 //extfunc->glDeleteSync(sync_fence);
850 //sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
851 main_mutex->unlock();
854 uVramTextureID->setData(*p, QOpenGLTexture::DontGenerateMipMaps);
857 // This sequence is *outside* of normal rendering phase, maybe using compute shader.
858 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
859 extfunc->glBindTexture(GL_TEXTURE_2D, uVramTextureID->textureId());
860 //extfunc->glActiveTexture(GL_TEXTURE0);
861 extfunc->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pixel_width, pixel_height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
862 extfunc->glBindTexture(GL_TEXTURE_2D, 0);
863 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
867 if(using_flags->is_support_tv_render() && (p_config->rendering_type == CONFIG_RENDER_TYPE_TV)) {
868 renderToTmpFrameBuffer_nPass(uVramTextureID->textureId(),
869 screen_texture_width,
870 screen_texture_height,
872 ntsc_pass1->getViewportWidth(),
873 ntsc_pass1->getViewportHeight());
875 renderToTmpFrameBuffer_nPass(ntsc_pass1->getTexture(),
876 ntsc_pass1->getViewportWidth(),
877 ntsc_pass1->getViewportHeight(),
879 ntsc_pass2->getViewportWidth(),
880 ntsc_pass2->getViewportHeight());
881 uTmpTextureID = ntsc_pass2->getTexture();
885 uTmpTextureID = uVramTextureID->textureId();
890 void GLDraw_4_5::drawScreenTexture(void)
892 if(using_flags->is_use_one_board_computer()) {
893 extfunc->glEnable(GL_BLEND);
894 extfunc->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
896 extfunc->glDisable(GL_BLEND);
900 smoosing = p_config->use_opengl_filters;
902 color = QVector4D(fBrightR, fBrightG, fBrightB, 1.0);
904 color = QVector4D(1.0, 1.0, 1.0, 1.0);
906 if(using_flags->is_use_one_board_computer()) {
908 uTmpTextureID, // v2.0
910 true, QVector3D(0.0, 0.0, 0.0));
911 extfunc->glDisable(GL_BLEND);
914 uTmpTextureID, // v2.0
919 void GLDraw_4_5::drawMain(QOpenGLShaderProgram *prg,
920 QOpenGLVertexArrayObject *vp,
934 extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
936 ortho.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
938 extfunc->glActiveTexture(GL_TEXTURE0);
939 extfunc->glBindTexture(GL_TEXTURE_2D, texid);
940 //extfunc->glBindTexture(GL_PIXEL_UNPACK_BUFFER, texid);
942 extfunc->glClearColor(1.0, 1.0, 1.0, 1.0);
944 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
945 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
947 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
948 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
950 prg->setUniformValue("a_texture", 0);
951 prg->setUniformValue("v_ortho", ortho);
953 ii = prg->uniformLocation("color");
955 prg->setUniformValue(ii, color);
958 ii = prg->uniformLocation("tex_width");
960 prg->setUniformValue(ii, (float)screen_texture_width);
963 ii = prg->uniformLocation("tex_height");
965 prg->setUniformValue(ii, (float)screen_texture_height);
968 switch(p_config->rotate_type) {
970 rot = QMatrix2x2(rot0);
973 rot = QMatrix2x2(rot90);
976 rot = QMatrix2x2(rot180);
979 rot = QMatrix2x2(rot270);
982 rot = QMatrix2x2(rot0);
985 prg->setUniformValue("rotate_mat", rot);
987 //prg->setUniformValue("rotate", GL_FALSE);
991 ii = prg->uniformLocation("chromakey");
993 prg->setUniformValue(ii, chromakey);
995 ii = prg->uniformLocation("do_chromakey");
997 prg->setUniformValue(ii, GL_TRUE);
1000 ii = prg->uniformLocation("do_chromakey");
1002 prg->setUniformValue(ii, GL_FALSE);
1006 prg->enableAttributeArray("texcoord");
1007 prg->enableAttributeArray("vertex");
1008 int vertex_loc = prg->attributeLocation("vertex");
1009 int texcoord_loc = prg->attributeLocation("texcoord");
1011 //prg->enableAttributeArray(vertex_loc);
1012 prg->setAttributeBuffer(vertex_loc, GL_FLOAT, 0, 3, sizeof(VertexTexCoord_t));
1013 prg->setAttributeBuffer(texcoord_loc, GL_FLOAT, 3 * sizeof(GLfloat), 2, sizeof(VertexTexCoord_t));
1014 extfunc->glEnableVertexAttribArray(vertex_loc);
1015 extfunc->glEnableVertexAttribArray(texcoord_loc);
1017 extfunc->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1022 extfunc->glBindTexture(GL_TEXTURE_2D, 0);
1023 //extfunc->glBindTexture(GL_TEXTURE_2D, 0);
1029 extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
1031 ortho.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
1032 //extfunc->glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
1033 ii = prg->uniformLocation("color");
1035 prg->setUniformValue(ii, color);
1038 switch(p_config->rotate_type) {
1040 rot = QMatrix2x2(rot0);
1043 rot = QMatrix2x2(rot90);
1046 rot = QMatrix2x2(rot180);
1049 rot = QMatrix2x2(rot270);
1052 rot = QMatrix2x2(rot0);
1055 prg->setUniformValue("rotate_mat", rot);
1056 prg->setUniformValue("v_ortho", ortho);
1059 ii = prg->uniformLocation("chromakey");
1061 prg->setUniformValue(ii, chromakey);
1063 ii = prg->uniformLocation("do_chromakey");
1065 prg->setUniformValue(ii, GL_TRUE);
1068 ii = prg->uniformLocation("do_chromakey");
1070 prg->setUniformValue(ii, GL_FALSE);
1074 prg->enableAttributeArray("vertex");
1075 int vertex_loc = prg->attributeLocation("vertex");
1076 extfunc->glEnableVertexAttribArray(vertex_loc);
1077 extfunc->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1081 extfunc->glBindTexture(GL_TEXTURE_2D, 0);
1084 extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
1085 extfunc->glDeleteSync(sync_fence);
1086 sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1089 void GLDraw_4_5::drawMain(GLScreenPack *obj,
1094 QVector3D chromakey)
1097 QOpenGLShaderProgram *prg = obj->getShader();
1098 QOpenGLVertexArrayObject *vp = obj->getVAO();
1099 QOpenGLBuffer *bp = obj->getVertexBuffer();
1101 drawMain(prg, vp, bp, texid, color, f_smoosing, do_chromakey, chromakey);
1104 void GLDraw_4_5::drawButtonsMain(int num, bool f_smoosing)
1106 GLuint texid = uButtonTextureID[num]->textureId();
1107 QOpenGLBuffer *bp = buffer_button_vertex[num];
1108 QOpenGLShaderProgram *prg = button_shader;
1109 QOpenGLVertexArrayObject *vp = vertex_button[num];
1113 color = QVector4D(1.0, 1.0, 1.0, 1.0);
1114 if((bp != NULL) && (vp != NULL) && (prg != NULL)) {
1115 if((bp->isCreated()) && (vp->isCreated()) && (prg->isLinked())) {
1120 ortho.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
1121 extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
1123 extfunc->glActiveTexture(GL_TEXTURE0);
1124 extfunc->glBindTexture(GL_TEXTURE_2D, texid);
1126 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1127 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
1129 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1130 extfunc->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1132 prg->setUniformValue("a_texture", 0);
1133 prg->setUniformValue("v_ortho", ortho);
1135 ii = prg->uniformLocation("color");
1137 prg->setUniformValue(ii, color);
1139 ii = prg->uniformLocation("do_chromakey");
1141 prg->setUniformValue(ii, GL_FALSE);
1144 switch(p_config->rotate_type) {
1146 rot = QMatrix2x2(rot0);
1149 rot = QMatrix2x2(rot90);
1152 rot = QMatrix2x2(rot180);
1155 rot = QMatrix2x2(rot270);
1158 rot = QMatrix2x2(rot0);
1161 prg->setUniformValue("rotate_mat", rot);
1163 int vertex_loc = prg->attributeLocation("vertex");
1164 int texcoord_loc = prg->attributeLocation("texcoord");
1165 prg->setAttributeBuffer(vertex_loc, GL_FLOAT, 0, 3, sizeof(VertexTexCoord_t));
1166 prg->setAttributeBuffer(texcoord_loc, GL_FLOAT, 3 * sizeof(GLfloat), 2, sizeof(VertexTexCoord_t));
1167 prg->enableAttributeArray(vertex_loc);
1168 prg->enableAttributeArray(texcoord_loc);
1169 //extfunc->glEnableVertexAttribArray(vertex_loc);
1170 //extfunc->glEnableVertexAttribArray(texcoord_loc);
1171 extfunc->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1175 extfunc->glBindTexture(GL_TEXTURE_2D, 0);
1182 void GLDraw_4_5::drawButtons(void)
1184 for(int i = 0; i < using_flags->get_max_button(); i++) {
1185 drawButtonsMain(i, false);
1189 void GLDraw_4_5::drawBitmapTexture(void)
1191 QVector4D color = QVector4D(1.0f, 1.0f, 1.0f, 1.0f);
1192 smoosing = p_config->use_opengl_filters;
1194 if(using_flags->is_use_one_board_computer() && (uBitmapTextureID != NULL)) {
1195 //extfunc->glDisable(GL_BLEND);
1196 drawMain(bitmap_block,
1197 uBitmapTextureID->textureId(),
1202 void GLDraw_4_5::drawLedMain(GLScreenPack *obj, int num, QVector4D color)
1204 QOpenGLShaderProgram *prg = obj->getShader();
1205 QOpenGLVertexArrayObject *vp = led_pass_vao[num];
1206 QOpenGLBuffer *bp = led_pass_vbuffer[num];
1210 extfunc->glEnable(GL_BLEND);
1211 extfunc->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1215 extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
1216 //extfunc->glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
1217 ii = prg->uniformLocation("color");
1219 prg->setUniformValue(ii, color);
1222 prg->enableAttributeArray("vertex");
1223 int vertex_loc = prg->attributeLocation("vertex");
1224 prg->setAttributeBuffer(vertex_loc, GL_FLOAT, 0, 3, sizeof(VertexTexCoord_t));
1225 extfunc->glVertexAttribPointer(vertex_loc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTexCoord_t), 0);
1227 extfunc->glEnableVertexAttribArray(vertex_loc);
1228 extfunc->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
1233 extfunc->glDisable(GL_BLEND);
1239 void GLDraw_4_5::drawOsdLeds()
1242 QVector4D color_off;
1243 uint32_t bit = 0x00000001;
1245 color_on = QVector4D(0.95, 0.0, 0.05, 1.0);
1246 color_off = QVector4D(0.05,0.05, 0.05, 0.10);
1248 color_on = QVector4D(0.00,0.00, 0.00, 0.0);
1249 color_off = QVector4D(0.00,0.00, 0.00, 0.0);
1252 //if(osd_led_status_bak != osd_led_status) {
1253 for(int i = 0; i < osd_led_bit_width; i++) {
1254 if((bit & osd_led_status) == (bit & osd_led_status_bak)) {
1258 drawLedMain(led_pass, i,
1259 ((osd_led_status & bit) != 0) ? color_on : color_off);
1262 osd_led_status_bak = osd_led_status;
1267 void GLDraw_4_5::drawOsdIcons()
1270 QVector4D color_off;
1271 uint32_t bit = 0x00000001;
1273 color_on = QVector4D(1.0, 1.0, 1.0, 0.8);
1274 color_off = QVector4D(1.0, 1.0, 1.0, 0.00);
1276 color_on = QVector4D(0.00,0.00, 0.00, 0.0);
1277 color_off = QVector4D(0.00,0.00, 0.00, 0.0);
1281 //if(osd_led_status_bak != osd_led_status) {
1282 for(int i = 0; i < osd_led_bit_width; i++) {
1283 if((bit & osd_led_status) == (bit & osd_led_status_bak)) {
1284 if((bit & osd_led_status) == 0) {
1289 if((i >= 2) && (i < 10)) { // FD
1292 } else if((i >= 10) && (i < 12)) { // QD
1295 } else if((i >= 12) && (i < 14)) { // CMT(R)
1298 } else if((i >= 14) && (i < 16)) { // CMT(W)
1306 drawMain(osd_pass->getShader(), osd_pass_vao[i], osd_pass_vbuffer[i],
1307 icon_texid[major][minor]->textureId(),
1308 ((osd_led_status & bit) != 0) ? color_on : color_off,
1309 false, false, QVector3D(0.0, 0.0, 0.0));
1313 osd_led_status_bak = osd_led_status;
1318 void GLDraw_4_5::paintGL(void)
1320 //p_wid->makeCurrent();
1322 // if(crt_flag || redraw_required) { //return;
1326 redraw_required = false;
1327 extfunc->glViewport(0, 0, p_wid->width(), p_wid->height());
1328 //extfunc->glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
1330 extfunc->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1331 extfunc->glDisable(GL_DEPTH_TEST);
1332 extfunc->glDisable(GL_BLEND);
1333 if(using_flags->is_use_one_board_computer() || using_flags->is_use_bitmap()) {
1334 extfunc->glEnable(GL_BLEND);
1335 drawBitmapTexture();
1337 if(using_flags->get_max_button() > 0) {
1338 extfunc->glEnable(GL_BLEND);
1341 drawScreenTexture();
1342 extfunc->glEnable(GL_BLEND);
1343 extfunc->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1344 extfunc->glDisable(GL_DEPTH_TEST);
1346 if(p_config->use_osd_virtual_media) drawOsdIcons();
1347 extfunc->glDisable(GL_BLEND);
1348 if(!using_flags->is_use_one_board_computer() && (using_flags->get_max_button() <= 0)) {
1354 void GLDraw_4_5::setBrightness(GLfloat r, GLfloat g, GLfloat b)
1360 if(imgptr != NULL) {
1361 p_wid->makeCurrent();
1362 if(uVramTextureID == NULL) {
1363 uVramTextureID = createMainTexture(imgptr);
1365 // if(using_flags->is_use_one_board_computer() || (using_flags->get_max_button() > 0)) {
1366 // uploadMainTexture(imgptr, true);
1368 // uploadMainTexture(imgptr, false);
1370 p_wid->doneCurrent();
1375 void GLDraw_4_5::set_texture_vertex(float wmul, float hmul)
1377 float wfactor = 1.0f;
1378 float hfactor = 1.0f;
1380 vertexTmpTexture[0].x = -1.0f;
1381 vertexTmpTexture[0].y = -1.0f;
1382 vertexTmpTexture[0].z = -0.1f;
1383 vertexTmpTexture[0].s = 0.0f;
1384 vertexTmpTexture[0].t = 0.0f;
1386 vertexTmpTexture[1].x = wfactor;
1387 vertexTmpTexture[1].y = -1.0f;
1388 vertexTmpTexture[1].z = -0.1f;
1389 vertexTmpTexture[1].s = wmul;
1390 vertexTmpTexture[1].t = 0.0f;
1392 vertexTmpTexture[2].x = wfactor;
1393 vertexTmpTexture[2].y = hfactor;
1394 vertexTmpTexture[2].z = -0.1f;
1395 vertexTmpTexture[2].s = wmul;
1396 vertexTmpTexture[2].t = hmul;
1398 vertexTmpTexture[3].x = -1.0f;
1399 vertexTmpTexture[3].y = hfactor;
1400 vertexTmpTexture[3].z = -0.1f;
1401 vertexTmpTexture[3].s = 0.0f;
1402 vertexTmpTexture[3].t = hmul;
1406 void GLDraw_4_5::set_osd_vertex(int xbit)
1408 float xbase, ybase, zbase;
1409 VertexTexCoord_t vertex[4];
1410 int major, minor, nl;
1412 if((xbit < 0) || (xbit >= 32)) return;
1413 if((i >= 2) && (i < 10)) { // FD
1416 nl = using_flags->get_max_drive();
1417 } else if((i >= 10) && (i < 12)) { // QD
1420 nl = using_flags->get_max_qd();
1421 } else if((i >= 12) && (i < 14)) { // CMT(R)
1424 nl = using_flags->get_max_tape();
1425 } else if((i >= 14) && (i < 16)) { // CMT(W)
1428 nl = using_flags->get_max_tape();
1429 } else if(i >= 16) {
1430 major = 4 + (i / 8) - 2;
1438 xbase = 1.0f - (1.0f * 48.0f / 640.0f) * (float)(nl - minor) - (4.0f / 640.0f);;
1439 ybase = -1.0f + (1.0f * 48.0f / 400.0f) * (float)(major + 1) + (4.0f / 400.0f);
1441 vertex[0].x = xbase;
1442 vertex[0].y = ybase;
1443 vertex[0].z = zbase;
1447 vertex[1].x = xbase + (48.0f / 640.0f);
1448 vertex[1].y = ybase;
1449 vertex[1].z = zbase;
1453 vertex[2].x = xbase + (48.0f / 640.0f);
1454 vertex[2].y = ybase - (48.0f / 400.0f);
1455 vertex[2].z = zbase;
1459 vertex[3].x = xbase;
1460 vertex[3].y = ybase - (48.0f / 400.0f);
1461 vertex[3].z = zbase;
1465 setNormalVAO(osd_pass->getShader(), osd_pass_vao[xbit],
1466 osd_pass_vbuffer[xbit],
1470 void GLDraw_4_5::set_led_vertex(int xbit)
1472 float xbase, ybase, zbase;
1473 VertexTexCoord_t vertex[4];
1475 if((xbit < 0) || (xbit >=32)) return;
1476 xbase = 0.0f + (1.0f / 32.0f) * 31.0f - ((1.0f * (float)xbit) / 32.0f) + (1.0f / 128.0f);
1477 ybase = -1.0f + (2.0f / 64.0f) * 1.5f;
1479 vertex[0].x = xbase;
1480 vertex[0].y = ybase;
1481 vertex[0].z = zbase;
1485 vertex[1].x = xbase + (1.0f / 64.0f);
1486 vertex[1].y = ybase;
1487 vertex[1].z = zbase;
1491 vertex[2].x = xbase + (1.0f / 64.0f);
1492 vertex[2].y = ybase - (1.0f / 64.0f);
1493 vertex[2].z = zbase;
1497 vertex[3].x = xbase;
1498 vertex[3].y = ybase - (1.0f / 64.0f);
1499 vertex[3].z = zbase;
1503 setNormalVAO(led_pass->getShader(), led_pass_vao[xbit],
1504 led_pass_vbuffer[xbit],
1508 void GLDraw_4_5::do_set_screen_multiply(float mul)
1510 screen_multiply = mul;
1511 do_set_texture_size(imgptr, screen_texture_width, screen_texture_height);
1514 void GLDraw_4_5::do_set_texture_size(QImage *p, int w, int h)
1516 if(w <= 0) w = using_flags->get_real_screen_width();
1517 if(h <= 0) h = using_flags->get_real_screen_height();
1521 iw = (float)p->width();
1522 ih = (float)p->height();
1524 iw = (float)using_flags->get_real_screen_width();
1525 ih = (float)using_flags->get_real_screen_height();
1527 //printf("%dx%d -> %fx%f\n", w, h, iw, ih);
1529 screen_texture_width = w;
1530 screen_texture_height = h;
1532 p_wid->makeCurrent();
1534 //set_texture_vertex(p, p_wid->width(), p_wid->height(), w, h);
1535 set_texture_vertex((float)w / iw, (float)h / ih);
1536 setNormalVAO(ntsc_pass1->getShader(), ntsc_pass1->getVAO(),
1537 ntsc_pass1->getVertexBuffer(),
1538 vertexTmpTexture, 4);
1540 set_texture_vertex(1.0f, 1.0f);
1541 setNormalVAO(ntsc_pass2->getShader(), ntsc_pass2->getVAO(),
1542 ntsc_pass2->getVertexBuffer(),
1543 vertexTmpTexture, 4);
1546 if(((int)iw != pixel_width) || ((int)ih != pixel_height)) {
1547 QImage im((int)screen_texture_width, (int)screen_texture_height, QImage::Format_RGBA8888);
1551 if(uVramTextureID != NULL) {
1552 p_wid->makeCurrent();
1553 uVramTextureID->destroy();
1554 delete uVramTextureID;
1555 uVramTextureID = createMainTexture(p);
1556 p_wid->doneCurrent();
1558 p_wid->makeCurrent();
1559 uVramTextureID = createMainTexture(p);
1560 p_wid->doneCurrent();
1563 vertexFormat[0].x = -1.0f;
1564 vertexFormat[0].y = -1.0f;
1565 vertexFormat[0].z = -0.9f;
1566 vertexFormat[1].x = 1.0f;
1567 vertexFormat[1].y = -1.0f;
1568 vertexFormat[1].z = -0.9f;
1569 vertexFormat[2].x = 1.0f;
1570 vertexFormat[2].y = 1.0f;
1571 vertexFormat[2].z = -0.9f;
1572 vertexFormat[3].x = -1.0f;
1573 vertexFormat[3].y = 1.0f;
1574 vertexFormat[3].z = -0.9f;
1576 vertexFormat[0].s = 0.0f;
1577 //vertexFormat[0].t = (float)h / ih;
1578 //vertexFormat[1].s = (float)w / iw;
1579 //vertexFormat[1].t = (float)h / ih;
1580 //vertexFormat[2].s = (float)w / iw;
1581 vertexFormat[0].t = 1.0f;
1582 vertexFormat[1].s = 1.0f;
1583 vertexFormat[1].t = 1.0f;
1584 vertexFormat[2].s = 1.0f;
1585 vertexFormat[2].t = 0.0f;
1586 vertexFormat[3].s = 0.0f;
1587 vertexFormat[3].t = 0.0f;
1589 setNormalVAO(main_pass->getShader(), main_pass->getVAO(),
1590 main_pass->getVertexBuffer(),
1593 if(w > using_flags->get_real_screen_width()) {
1594 w = using_flags->get_real_screen_width();
1596 if(h > using_flags->get_real_screen_height()) {
1597 h = using_flags->get_real_screen_height();
1599 this->doSetGridsHorizonal(h, false);
1600 this->doSetGridsVertical(w, false);
1601 p_wid->doneCurrent();
1604 void GLDraw_4_5::do_set_horiz_lines(int lines)
1606 if(lines > using_flags->get_real_screen_height()) {
1607 lines = using_flags->get_real_screen_height();
1609 this->doSetGridsHorizonal(lines, false);
1612 void GLDraw_4_5::resizeGL_Screen(void)
1614 if(main_pass != NULL) {
1615 setNormalVAO(main_pass->getShader(), main_pass->getVAO(),
1616 main_pass->getVertexBuffer(),
1621 void GLDraw_4_5::resizeGL(int width, int height)
1623 //int side = qMin(width, height);
1624 extfunc->glViewport(0, 0, width, height);
1625 //extfunc->glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0);
1627 if(!using_flags->is_use_one_board_computer() && (using_flags->get_max_button() <= 0)) {
1628 doSetGridsHorizonal(vert_lines, true);
1629 if(using_flags->is_use_vertical_pixel_lines()) {
1630 doSetGridsVertical(horiz_pixels, true);
1633 resizeGL_SetVertexs();
1635 if(using_flags->is_use_one_board_computer()) {
1636 setNormalVAO(bitmap_block->getShader(), bitmap_block->getVAO(),
1637 bitmap_block->getVertexBuffer(),
1640 if(using_flags->get_max_button() > 0) {
1641 updateButtonTexture();
1645 void GLDraw_4_5::initButtons(void)
1647 button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
1648 QOpenGLContext *context = QOpenGLContext::currentContext();
1649 QPair<int, int> _version = QOpenGLVersionProfile(context->format()).version();
1650 QString versionext = QString::fromUtf8("");
1651 if(((_version.first == 4) && (_version.second >= 3)) || (_version.first >= 5)) {
1652 versionext = QString::fromUtf8("#version 430 core \n"); // OK?
1653 } else if((_version.first == 4)) {
1654 versionext = QString::fromUtf8("#version 400 core \n");
1655 } else { // Require GLVersion >= 3.2
1656 versionext = QString::fromUtf8("#version 150 \n");
1659 if(vm_buttons_d != NULL) {
1660 button_shader = new QOpenGLShaderProgram(p_wid);
1661 if(button_shader != NULL) {
1663 QFile vertex_src(QString::fromUtf8(":/gl4_5/vertex_shader.glsl"));
1664 if (vertex_src.open(QIODevice::ReadOnly | QIODevice::Text)) {
1665 QString srcs = versionext;
1666 srcs = srcs + QString::fromUtf8(vertex_src.readAll());
1667 f = button_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, srcs);
1672 QFile fragment_src(QString::fromUtf8(":/gl4_5/normal_fragment_shader.glsl"));
1673 if (fragment_src.open(QIODevice::ReadOnly | QIODevice::Text)) {
1674 QString srcs = versionext;
1675 srcs = srcs + QString::fromUtf8(fragment_src.readAll());
1676 f &= button_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, srcs);
1677 fragment_src.close();
1682 button_shader->link();
1685 int ip = using_flags->get_max_button();
1687 for(int num = 0; num < ip; num++) {
1689 tmps = QString::asprintf(":/button%02d.png", num);
1690 QImageReader *reader = new QImageReader(tmps);
1691 QImage *result = new QImage(reader->read());
1693 if(result != NULL) {
1694 if(!result->isNull()) {
1695 pic = result->convertToFormat(QImage::Format_ARGB32);
1697 pic = QImage(10, 10, QImage::Format_RGBA8888);
1698 pic.fill(QColor(0,0,0,0));
1702 pic = QImage(10, 10, QImage::Format_RGBA8888);
1703 pic.fill(QColor(0,0,0,0));
1705 ButtonImages.push_back(pic);
1708 vertexButtons = new QVector<VertexTexCoord_t>;
1709 for(int i = 0; i < using_flags->get_max_button(); i++) {
1710 buffer_button_vertex[i] = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
1711 buffer_button_vertex[i]->create();
1712 fButtonX[i] = -1.0 + (float)(vm_buttons_d[i].x * 2) / (float)using_flags->get_screen_width();
1713 fButtonY[i] = 1.0 - (float)(vm_buttons_d[i].y * 2) / (float)using_flags->get_screen_height();
1714 fButtonWidth[i] = (float)(vm_buttons_d[i].width * 2) / (float)using_flags->get_screen_width();
1715 fButtonHeight[i] = (float)(vm_buttons_d[i].height * 2) / (float)using_flags->get_screen_height();
1717 vertex_button[i] = new QOpenGLVertexArrayObject;
1718 if(vertex_button[i] != NULL) {
1719 if(vertex_button[i]->create()) {
1720 VertexTexCoord_t vt[4];
1722 vt[0].x = fButtonX[i];
1723 vt[0].y = fButtonY[i];
1728 vt[1].x = fButtonX[i] + fButtonWidth[i];
1729 vt[1].y = fButtonY[i];
1734 vt[2].x = fButtonX[i] + fButtonWidth[i];
1735 vt[2].y = fButtonY[i] - fButtonHeight[i];
1740 vt[3].x = fButtonX[i];
1741 vt[3].y = fButtonY[i] - fButtonHeight[i];
1746 vertexButtons->append(vt[0]);
1747 vertexButtons->append(vt[1]);
1748 vertexButtons->append(vt[2]);
1749 vertexButtons->append(vt[3]);
1750 vertex_button[i]->bind();
1751 buffer_button_vertex[i]->bind();
1752 buffer_button_vertex[i]->allocate(4 * sizeof(VertexTexCoord_t));
1754 buffer_button_vertex[i]->setUsagePattern(QOpenGLBuffer::StaticDraw);
1755 buffer_button_vertex[i]->release();
1756 vertex_button[i]->release();
1757 setNormalVAO(button_shader, vertex_button[i],
1758 buffer_button_vertex[i],
1766 void GLDraw_4_5::do_set_display_osd(bool onoff)
1771 void GLDraw_4_5::do_display_osd_leds(int lednum, bool onoff)
1774 osd_led_status = (onoff) ? 0xffffffff : 0x00000000;
1775 } else if((lednum >= 0) && (lednum < 32)) {
1777 nn = 0x00000001 << lednum;
1779 osd_led_status |= nn;
1781 osd_led_status &= ~nn;
1786 void GLDraw_4_5::uploadIconTexture(QPixmap *p, int icon_type, int localnum)
1788 if((icon_type > 7) || (icon_type < 0)) return;
1789 if((localnum >= 9) || (localnum < 0)) return;
1790 if(p == NULL) return;
1791 p_wid->makeCurrent();
1792 QImage image = p->toImage();
1794 if(icon_texid[icon_type][localnum] != NULL) delete icon_texid[icon_type][localnum];
1796 icon_texid[icon_type][localnum] = new QOpenGLTexture(image);
1798 p_wid->doneCurrent();
1803 void GLDraw_4_5::updateBitmap(QImage *p)
1805 if(!using_flags->is_use_one_board_computer()) return;
1806 redraw_required = true;
1807 bitmap_uploaded = false;
1808 uploadBitmapTexture(p);
1811 void GLDraw_4_5::uploadBitmapTexture(QImage *p)
1813 if(!using_flags->is_use_one_board_computer()) return;
1814 if(p == NULL) return;
1815 if(!bitmap_uploaded) {
1816 p_wid->makeCurrent();
1817 if(uBitmapTextureID != NULL) {
1818 delete uBitmapTextureID;
1820 uBitmapTextureID = new QOpenGLTexture(*p);
1821 p_wid->doneCurrent();
1822 bitmap_uploaded = true;
1827 void GLDraw_4_5::updateButtonTexture(void)
1830 button_desc_t *vm_buttons_d = using_flags->get_vm_buttons();
1831 if(button_updated) return;
1832 if(vm_buttons_d != NULL) {
1833 for(i = 0; i < using_flags->get_max_button(); i++) {
1834 QImage img = ButtonImages.at(i);
1835 if(uButtonTextureID[i] != NULL) {
1836 delete uButtonTextureID[i];
1838 uButtonTextureID[i] = new QOpenGLTexture(img);
1841 button_updated = true;
1844 void GLDraw_4_5::get_screen_geometry(int *w, int *h)
1846 if(w != NULL) *w = pixel_width;
1847 if(h != NULL) *h = pixel_height;
1850 scrntype_t *GLDraw_4_5::get_screen_buffer(int y)
1852 if((y < 0) || (y >= pixel_height)) return NULL;
1853 if((map_base_address == NULL) || !(main_texture_ready)) {
1857 extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
1858 extfunc->glDeleteSync(sync_fence);
1859 sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1861 scrntype_t *p = (scrntype_t *)map_base_address;
1862 p = p + (pixel_width * y);
1863 //printf("%08x\n", (uintptr_t)p);
1864 main_mutex->unlock();
1868 // Note: Mapping vram from draw_thread does'nt work well.
1869 // This feature might be disable. 20180728 K.Ohta.
1870 bool GLDraw_4_5::is_ready_to_map_vram_texture(void)
1872 if(main_texture_buffer == 0) {
1875 if(gl_major_version < 4) {
1878 if(gl_minor_version < 4) {
1884 bool GLDraw_4_5::map_vram_texture(void)
1886 if(main_texture_buffer == 0) {
1889 // if(!(main_texture_ready)) {
1893 if(gl_major_version < 4) {
1896 if(gl_minor_version < 4) {
1903 extfunc->glClientWaitSync(sync_fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
1904 extfunc->glDeleteSync(sync_fence);
1905 sync_fence = extfunc->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1907 //extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
1908 map_base_address = (scrntype_t *)(extfunc->glMapNamedBufferRange(main_texture_buffer, 0, pixel_width * pixel_height * sizeof(scrntype_t), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT));
1909 csp_logger->debug_log(CSP_LOG_INFO, CSP_LOG_TYPE_SCREEN, "MAPPED SCREEN TO PHYSICAL ADDRESS:%0llx\n", (uintptr_t)map_base_address);
1910 //extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1911 if(map_base_address == NULL) return false;
1916 bool GLDraw_4_5::unmap_vram_texture(void)
1918 if((map_base_address == NULL) || (main_texture_buffer == 0)) return false;
1920 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, main_texture_buffer);
1921 extfunc->glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1922 extfunc->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);