Changeset View
Changeset View
Standalone View
Standalone View
platformsupport/scenes/opengl/abstract_egl_backend.cpp
Show First 20 Lines • Show All 428 Lines • ▼ Show 20 Line(s) | 376 | { | |||
---|---|---|---|---|---|
429 | } | 429 | } | ||
430 | if (image.size() != m_size) { | 430 | if (image.size() != m_size) { | ||
431 | // buffer size has changed, reload shm texture | 431 | // buffer size has changed, reload shm texture | ||
432 | if (!loadTexture(pixmap)) { | 432 | if (!loadTexture(pixmap)) { | ||
433 | return; | 433 | return; | ||
434 | } | 434 | } | ||
435 | } | 435 | } | ||
436 | Q_ASSERT(image.size() == m_size); | 436 | Q_ASSERT(image.size() == m_size); | ||
437 | q->bind(); | | |||
438 | const QRegion damage = s->trackedDamage(); | 437 | const QRegion damage = s->trackedDamage(); | ||
439 | s->resetTrackedDamage(); | 438 | s->resetTrackedDamage(); | ||
440 | auto scale = s->scale(); //damage is normalised, so needs converting up to match texture | | |||
441 | 439 | | |||
442 | // TODO: this should be shared with GLTexture::update | 440 | // TODO: this should be shared with GLTexture::update | ||
443 | if (GLPlatform::instance()->isGLES()) { | 441 | createTextureSubImage(s->scale(), image, damage); | ||
444 | if (s_supportsARGB32 && (image.format() == QImage::Format_ARGB32 || image.format() == QImage::Format_ARGB32_Premultiplied)) { | | |||
445 | const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | | |||
446 | for (const QRect &rect : damage) { | | |||
447 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | | |||
448 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | | |||
449 | GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | | |||
450 | } | | |||
451 | } else { | | |||
452 | const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); | | |||
453 | for (const QRect &rect : damage) { | | |||
454 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | | |||
455 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | | |||
456 | GL_RGBA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | | |||
457 | } | | |||
458 | } | | |||
459 | } else { | | |||
460 | const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | | |||
461 | for (const QRect &rect : damage) { | | |||
462 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | | |||
463 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | | |||
464 | GL_BGRA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | | |||
465 | } | | |||
466 | } | | |||
467 | q->unbind(); | | |||
468 | } | 442 | } | ||
469 | 443 | | |||
470 | bool AbstractEglTexture::loadShmTexture(const QPointer< KWayland::Server::BufferInterface > &buffer) | 444 | bool AbstractEglTexture::createTextureImage(const QImage &image) | ||
471 | { | 445 | { | ||
472 | const QImage &image = buffer->data(); | | |||
473 | if (image.isNull()) { | 446 | if (image.isNull()) { | ||
474 | return false; | 447 | return false; | ||
475 | } | 448 | } | ||
476 | 449 | | |||
477 | glGenTextures(1, &m_texture); | 450 | glGenTextures(1, &m_texture); | ||
478 | q->setWrapMode(GL_CLAMP_TO_EDGE); | | |||
479 | q->setFilter(GL_LINEAR); | 451 | q->setFilter(GL_LINEAR); | ||
480 | q->bind(); | 452 | q->setWrapMode(GL_CLAMP_TO_EDGE); | ||
zzag: Unnecessary shuffling of lines. | |||||
481 | 453 | | |||
454 | q->bind(); | ||||
482 | const QSize &size = image.size(); | 455 | const QSize &size = image.size(); | ||
483 | // TODO: this should be shared with GLTexture(const QImage&, GLenum) | | |||
484 | GLenum format = 0; | 456 | GLenum format = 0; | ||
485 | switch (image.format()) { | 457 | switch (image.format()) { | ||
486 | case QImage::Format_ARGB32: | 458 | case QImage::Format_ARGB32: | ||
487 | case QImage::Format_ARGB32_Premultiplied: | 459 | case QImage::Format_ARGB32_Premultiplied: | ||
488 | format = GL_RGBA8; | 460 | format = GL_RGBA8; | ||
489 | break; | 461 | break; | ||
490 | case QImage::Format_RGB32: | 462 | case QImage::Format_RGB32: | ||
491 | format = GL_RGB8; | 463 | format = GL_RGB8; | ||
Show All 10 Lines | 473 | } else { | |||
502 | const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); | 474 | const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); | ||
503 | glTexImage2D(m_target, 0, GL_RGBA, im.width(), im.height(), | 475 | glTexImage2D(m_target, 0, GL_RGBA, im.width(), im.height(), | ||
504 | 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits()); | 476 | 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits()); | ||
505 | } | 477 | } | ||
506 | } else { | 478 | } else { | ||
507 | glTexImage2D(m_target, 0, format, size.width(), size.height(), 0, | 479 | glTexImage2D(m_target, 0, format, size.width(), size.height(), 0, | ||
508 | GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); | 480 | GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); | ||
509 | } | 481 | } | ||
510 | | ||||
511 | q->unbind(); | 482 | q->unbind(); | ||
512 | q->setYInverted(true); | 483 | | ||
513 | m_size = size; | 484 | m_size = size; | ||
485 | q->setYInverted(true); | ||||
514 | updateMatrix(); | 486 | updateMatrix(); | ||
zzag: Unnecessary shuffling of lines. Please undo it. | |||||
515 | return true; | 487 | return true; | ||
I don't follow this change. setYInverted() must be called before updateMatrix(). Is there a reason why you swapped them? zzag: I don't follow this change. setYInverted() must be called before updateMatrix(). Is there a… | |||||
516 | } | 488 | } | ||
517 | 489 | | |||
490 | void AbstractEglTexture::createTextureSubImage(int scale, const QImage &image, const QRegion &damage) | ||||
491 | { | ||||
492 | q->bind(); | ||||
493 | if (GLPlatform::instance()->isGLES()) { | ||||
494 | if (s_supportsARGB32 && (image.format() == QImage::Format_ARGB32 || image.format() == QImage::Format_ARGB32_Premultiplied)) { | ||||
495 | const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | ||||
496 | for (const QRect &rect : damage) { | ||||
497 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | ||||
498 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | ||||
499 | GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | ||||
500 | } | ||||
501 | } else { | ||||
502 | const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); | ||||
503 | for (const QRect &rect : damage) { | ||||
504 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | ||||
505 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | ||||
506 | GL_RGBA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | ||||
507 | } | ||||
508 | } | ||||
509 | } else { | ||||
510 | const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | ||||
511 | for (const QRect &rect : damage) { | ||||
512 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | ||||
513 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | ||||
514 | GL_BGRA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | ||||
515 | } | ||||
516 | } | ||||
517 | q->unbind(); | ||||
518 | } | ||||
519 | | ||||
520 | bool AbstractEglTexture::loadShmTexture(const QPointer< KWayland::Server::BufferInterface > &buffer) | ||||
521 | { | ||||
522 | return createTextureImage(buffer->data()); | ||||
523 | } | ||||
524 | | ||||
518 | bool AbstractEglTexture::loadEglTexture(const QPointer< KWayland::Server::BufferInterface > &buffer) | 525 | bool AbstractEglTexture::loadEglTexture(const QPointer< KWayland::Server::BufferInterface > &buffer) | ||
519 | { | 526 | { | ||
520 | if (!eglQueryWaylandBufferWL) { | 527 | if (!eglQueryWaylandBufferWL) { | ||
521 | return false; | 528 | return false; | ||
522 | } | 529 | } | ||
523 | if (!buffer->resource()) { | 530 | if (!buffer->resource()) { | ||
524 | return false; | 531 | return false; | ||
525 | } | 532 | } | ||
Show All 35 Lines | 551 | { | |||
561 | m_size = dmabuf->size(); | 568 | m_size = dmabuf->size(); | ||
562 | q->setYInverted(!(dmabuf->flags() & KWayland::Server::LinuxDmabufUnstableV1Interface::YInverted)); | 569 | q->setYInverted(!(dmabuf->flags() & KWayland::Server::LinuxDmabufUnstableV1Interface::YInverted)); | ||
563 | 570 | | |||
564 | return true; | 571 | return true; | ||
565 | } | 572 | } | ||
566 | 573 | | |||
567 | bool AbstractEglTexture::loadInternalImageObject(WindowPixmap *pixmap) | 574 | bool AbstractEglTexture::loadInternalImageObject(WindowPixmap *pixmap) | ||
568 | { | 575 | { | ||
569 | // FIXME: Share some code with loadShmTexture(). | 576 | return createTextureImage(pixmap->internalImage()); | ||
570 | | ||||
571 | const QImage image = pixmap->internalImage(); | | |||
572 | if (image.isNull()) { | | |||
573 | return false; | | |||
574 | } | | |||
575 | | ||||
576 | glGenTextures(1, &m_texture); | | |||
577 | q->setFilter(GL_LINEAR); | | |||
578 | q->setWrapMode(GL_CLAMP_TO_EDGE); | | |||
579 | q->setYInverted(true); | | |||
580 | q->bind(); | | |||
581 | | ||||
582 | const QSize &size = image.size(); | | |||
583 | // TODO: this should be shared with GLTexture(const QImage&, GLenum) | | |||
584 | GLenum format = 0; | | |||
585 | switch (image.format()) { | | |||
586 | case QImage::Format_ARGB32: | | |||
587 | case QImage::Format_ARGB32_Premultiplied: | | |||
588 | format = GL_RGBA8; | | |||
589 | break; | | |||
590 | case QImage::Format_RGB32: | | |||
591 | format = GL_RGB8; | | |||
592 | break; | | |||
593 | default: | | |||
594 | return false; | | |||
595 | } | | |||
596 | if (GLPlatform::instance()->isGLES()) { | | |||
597 | if (s_supportsARGB32 && format == GL_RGBA8) { | | |||
598 | const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | | |||
599 | glTexImage2D(m_target, 0, GL_BGRA_EXT, im.width(), im.height(), | | |||
600 | 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.bits()); | | |||
601 | } else { | | |||
602 | const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); | | |||
603 | glTexImage2D(m_target, 0, GL_RGBA, im.width(), im.height(), | | |||
604 | 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits()); | | |||
605 | } | | |||
606 | } else { | | |||
607 | glTexImage2D(m_target, 0, format, size.width(), size.height(), 0, | | |||
608 | GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); | | |||
609 | } | | |||
610 | | ||||
611 | q->unbind(); | | |||
612 | | ||||
613 | m_size = size; | | |||
614 | updateMatrix(); | | |||
615 | | ||||
616 | return true; | | |||
617 | } | 577 | } | ||
618 | 578 | | |||
619 | EGLImageKHR AbstractEglTexture::attach(const QPointer< KWayland::Server::BufferInterface > &buffer) | 579 | EGLImageKHR AbstractEglTexture::attach(const QPointer< KWayland::Server::BufferInterface > &buffer) | ||
620 | { | 580 | { | ||
621 | EGLint format, yInverted; | 581 | EGLint format, yInverted; | ||
622 | eglQueryWaylandBufferWL(m_backend->eglDisplay(), buffer->resource(), EGL_TEXTURE_FORMAT, &format); | 582 | eglQueryWaylandBufferWL(m_backend->eglDisplay(), buffer->resource(), EGL_TEXTURE_FORMAT, &format); | ||
623 | if (format != EGL_TEXTURE_RGB && format != EGL_TEXTURE_RGBA) { | 583 | if (format != EGL_TEXTURE_RGB && format != EGL_TEXTURE_RGBA) { | ||
624 | qCDebug(KWIN_OPENGL) << "Unsupported texture format: " << format; | 584 | qCDebug(KWIN_OPENGL) << "Unsupported texture format: " << format; | ||
Show All 30 Lines | 608 | { | |||
655 | q->setFilter(GL_LINEAR); | 615 | q->setFilter(GL_LINEAR); | ||
656 | q->setYInverted(false); | 616 | q->setYInverted(false); | ||
657 | updateMatrix(); | 617 | updateMatrix(); | ||
658 | return true; | 618 | return true; | ||
659 | } | 619 | } | ||
660 | 620 | | |||
661 | bool AbstractEglTexture::updateFromInternalImageObject(WindowPixmap *pixmap) | 621 | bool AbstractEglTexture::updateFromInternalImageObject(WindowPixmap *pixmap) | ||
662 | { | 622 | { | ||
663 | // FIXME: Share some code with the shm fallback in updateTexture(). | | |||
664 | | ||||
665 | const QImage image = pixmap->internalImage(); | 623 | const QImage image = pixmap->internalImage(); | ||
666 | if (image.isNull()) { | 624 | if (image.isNull()) { | ||
667 | return false; | 625 | return false; | ||
668 | } | 626 | } | ||
669 | 627 | | |||
670 | if (m_size != image.size()) { | 628 | if (m_size != image.size()) { | ||
671 | glDeleteTextures(1, &m_texture); | 629 | glDeleteTextures(1, &m_texture); | ||
672 | return loadInternalImageObject(pixmap); | 630 | return loadInternalImageObject(pixmap); | ||
673 | } | 631 | } | ||
674 | 632 | | |||
675 | const QRegion damage = pixmap->toplevel()->damage(); | 633 | createTextureSubImage(image.devicePixelRatio(), image, pixmap->toplevel()->damage()); | ||
676 | const qreal scale = image.devicePixelRatio(); | | |||
677 | | ||||
678 | q->bind(); | | |||
679 | | ||||
680 | // TODO: this should be shared with GLTexture::update | | |||
681 | if (GLPlatform::instance()->isGLES()) { | | |||
682 | if (s_supportsARGB32 && (image.format() == QImage::Format_ARGB32 || image.format() == QImage::Format_ARGB32_Premultiplied)) { | | |||
683 | const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | | |||
684 | for (const QRect &rect : damage) { | | |||
685 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | | |||
686 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | | |||
687 | GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | | |||
688 | } | | |||
689 | } else { | | |||
690 | const QImage im = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); | | |||
691 | for (const QRect &rect : damage) { | | |||
692 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | | |||
693 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | | |||
694 | GL_RGBA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | | |||
695 | } | | |||
696 | } | | |||
697 | } else { | | |||
698 | const QImage im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); | | |||
699 | for (const QRect &rect : damage) { | | |||
700 | auto scaledRect = QRect(rect.x() * scale, rect.y() * scale, rect.width() * scale, rect.height() * scale); | | |||
701 | glTexSubImage2D(m_target, 0, scaledRect.x(), scaledRect.y(), scaledRect.width(), scaledRect.height(), | | |||
702 | GL_BGRA, GL_UNSIGNED_BYTE, im.copy(scaledRect).bits()); | | |||
703 | } | | |||
704 | } | | |||
705 | | ||||
706 | q->unbind(); | | |||
707 | 634 | | |||
708 | return true; | 635 | return true; | ||
709 | } | 636 | } | ||
710 | 637 | | |||
711 | } | 638 | } | ||
712 | 639 | |
Unnecessary shuffling of lines.