Changeset 846 for trunk/src/opengl/qwindowsurface_gl.cpp
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/opengl/qwindowsurface_gl.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 83 83 #endif 84 84 85 #ifdef QT_OPENGL_ES_1_CL 86 #include "qgl_cl_p.h" 87 #endif 88 89 #ifdef QT_OPENGL_ES 90 #include <private/qegl_p.h> 85 #ifndef QT_NO_EGL 86 #include <private/qeglcontext_p.h> 91 87 #endif 92 88 … … 99 95 extern Q_GUI_EXPORT bool qt_win_owndc_required; 100 96 #endif 101 QGLGraphicsSystem::QGLGraphicsSystem( )102 : QGraphicsSystem() 97 QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) 98 : QGraphicsSystem(), m_useX11GL(useX11GL) 103 99 { 104 100 #if defined(Q_WS_X11) && !defined(QT_OPENGL_ES) … … 195 191 if (!initializing && !widget && !cleanedUp) { 196 192 initializing = true; 197 widget = new QGLWidget; 198 // We dont need this internal widget to appear in QApplication::topLevelWidgets() 193 194 widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer)); 195 widget->resize(1, 1); 196 197 // We don't need this internal widget to appear in QApplication::topLevelWidgets() 199 198 if (QWidgetPrivate::allWidgets) 200 199 QWidgetPrivate::allWidgets->remove(widget); … … 204 203 } 205 204 205 // destroys the share widget and prevents recreation 206 206 void cleanup() { 207 207 QGLWidget *w = widget; … … 211 211 } 212 212 213 // destroys the share widget, but allows it to be recreated later on 214 void destroy() { 215 if (cleanedUp) 216 return; 217 218 QGLWidget *w = widget; 219 220 // prevent potential recursions 221 cleanedUp = true; 222 widget = 0; 223 delete w; 224 cleanedUp = false; 225 } 226 213 227 static bool cleanedUp; 214 228 … … 238 252 } 239 253 254 void qt_destroy_gl_share_widget() 255 { 256 _qt_gl_share_widget()->destroy(); 257 } 240 258 241 259 struct QGLWindowSurfacePrivate … … 250 268 int destructive_swap_buffers : 1; 251 269 int geometry_updated : 1; 270 int did_paint : 1; 252 271 253 272 QGLContext *ctx; … … 257 276 QRegion paintedRegion; 258 277 QSize size; 278 279 QSize textureSize; 259 280 260 281 QList<QImage> buffers; … … 264 285 265 286 QGLFormat QGLWindowSurface::surfaceFormat; 287 QGLWindowSurface::SwapMode QGLWindowSurface::swapBehavior = QGLWindowSurface::AutomaticSwap; 266 288 267 289 void QGLWindowSurfaceGLPaintDevice::endPaint() … … 299 321 d_ptr->fbo = 0; 300 322 d_ptr->ctx = 0; 323 d_ptr->tex_id = 0; 301 324 #if defined (QT_OPENGL_ES_2) 302 325 d_ptr->tried_fbo = true; … … 310 333 d_ptr->q_ptr = this; 311 334 d_ptr->geometry_updated = false; 335 d_ptr->did_paint = false; 312 336 } 313 337 … … 328 352 void QGLWindowSurface::deleted(QObject *object) 329 353 { 330 // Make sure that the fbo is destroyed before destroying its context.331 delete d_ptr->fbo;332 d_ptr->fbo = 0;333 334 354 QWidget *widget = qobject_cast<QWidget *>(object); 335 355 if (widget) { 356 if (widget == window()) { 357 // Make sure that the fbo is destroyed before destroying its context. 358 delete d_ptr->fbo; 359 d_ptr->fbo = 0; 360 } 361 336 362 QWidgetPrivate *widgetPrivate = widget->d_func(); 337 363 if (widgetPrivate->extraData()) { … … 355 381 return; 356 382 357 QGLContext *ctx = new QGLContext(surfaceFormat, widget); 383 QGLContext *ctx = NULL; 384 385 // For translucent top-level widgets we need alpha in the format. 386 if (widget->testAttribute(Qt::WA_TranslucentBackground)) { 387 QGLFormat modFormat(surfaceFormat); 388 modFormat.setSampleBuffers(false); 389 modFormat.setSamples(0); 390 modFormat.setAlpha(true); 391 ctx = new QGLContext(modFormat, widget); 392 } else 393 ctx = new QGLContext(surfaceFormat, widget); 394 358 395 ctx->create(qt_gl_share_widget()->context()); 359 396 360 #if defined(Q_WS_X11) && defined(QT_OPENGL_ES) 361 // Create the EGL surface to draw into. QGLContext::chooseContext() 362 // does not do this for X11/EGL, but does do it for other platforms. 363 // This probably belongs in qgl_x11egl.cpp. 364 QGLContextPrivate *ctxpriv = ctx->d_func(); 365 ctxpriv->eglSurface = ctxpriv->eglContext->createSurface(widget); 366 if (ctxpriv->eglSurface == EGL_NO_SURFACE) { 367 qWarning() << "hijackWindow() could not create EGL surface"; 368 } 369 qDebug("QGLWindowSurface - using EGLConfig %d", reinterpret_cast<int>(ctxpriv->eglContext->config())); 397 #ifndef QT_NO_EGL 398 static bool checkedForNOKSwapRegion = false; 399 static bool haveNOKSwapRegion = false; 400 401 if (!checkedForNOKSwapRegion) { 402 haveNOKSwapRegion = QEgl::hasExtension("EGL_NOK_swap_region2"); 403 checkedForNOKSwapRegion = true; 404 405 if (haveNOKSwapRegion) 406 qDebug() << "Found EGL_NOK_swap_region2 extension. Using partial updates."; 407 } 408 409 if (ctx->d_func()->eglContext->configAttrib(EGL_SWAP_BEHAVIOR) != EGL_BUFFER_PRESERVED && 410 ! haveNOKSwapRegion) 411 setPartialUpdateSupport(false); // Force full-screen updates 412 else 413 setPartialUpdateSupport(true); 370 414 #endif 371 415 … … 398 442 QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); 399 443 ctx->makeCurrent(); 444 445 Q_ASSERT(d_ptr->fbo); 400 446 return d_ptr->fbo; 401 447 } … … 405 451 void QGLWindowSurface::beginPaint(const QRegion &) 406 452 { 453 if (!context()) 454 return; 455 456 int clearFlags = 0; 457 458 if (context()->d_func()->workaround_needsFullClearOnEveryFrame) 459 clearFlags = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; 460 else if (context()->format().alpha()) 461 clearFlags = GL_COLOR_BUFFER_BIT; 462 463 if (clearFlags) { 464 glClearColor(0.0, 0.0, 0.0, 0.0); 465 glClear(clearFlags); 466 } 467 468 d_ptr->did_paint = true; 407 469 } 408 470 … … 415 477 } 416 478 479 static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, const QSize &texSize, const QRect &targetRect, const QRect &sourceRect) 480 { 481 glDisable(GL_DEPTH_TEST); 482 glDisable(GL_SCISSOR_TEST); 483 glDisable(GL_BLEND); 484 485 glViewport(0, 0, viewport.width(), viewport.height()); 486 487 QGLShaderProgram *blitProgram = 488 QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram(); 489 blitProgram->bind(); 490 blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); 491 492 // The shader manager's blit program does not multiply the 493 // vertices by the pmv matrix, so we need to do the effect 494 // of the orthographic projection here ourselves. 495 QRectF r; 496 qreal w = viewport.width(); 497 qreal h = viewport.height(); 498 r.setLeft((targetRect.left() / w) * 2.0f - 1.0f); 499 if (targetRect.right() == (viewport.width() - 1)) 500 r.setRight(1.0f); 501 else 502 r.setRight((targetRect.right() / w) * 2.0f - 1.0f); 503 r.setBottom((targetRect.top() / h) * 2.0f - 1.0f); 504 if (targetRect.bottom() == (viewport.height() - 1)) 505 r.setTop(1.0f); 506 else 507 r.setTop((targetRect.bottom() / w) * 2.0f - 1.0f); 508 509 drawTexture(r, texture, texSize, sourceRect); 510 } 511 512 417 513 void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) 418 514 { 419 if (context() && widget != window()) {420 qWarning("No native child widget support in GL window surface without FBOs or pixel buffers");421 return;422 }423 424 515 //### Find out why d_ptr->geometry_updated isn't always false. 425 516 // flush() should not be called when d_ptr->geometry_updated is true. It assumes that either … … 428 519 return; 429 520 521 // did_paint is set to true in ::beginPaint. ::beginPaint means that we 522 // at least cleared the background (= painted something). In EGL API it's a 523 // mistake to call swapBuffers if nothing was painted unless 524 // EGL_BUFFER_PRESERVED is set. This check protects the flush func from 525 // being executed if it's for nothing. 526 if (!hasPartialUpdateSupport() && !d_ptr->did_paint) 527 return; 528 430 529 QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); 431 530 Q_ASSERT(parent); … … 444 543 const GLenum target = GL_TEXTURE_2D; 445 544 Q_UNUSED(target); 545 546 if (QGLWindowSurface::swapBehavior == QGLWindowSurface::KillSwap) 547 return; 446 548 447 549 if (context()) { … … 492 594 } 493 595 #endif 596 bool doingPartialUpdate = false; 597 if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AutomaticSwap) 598 doingPartialUpdate = hasPartialUpdateSupport() && br.width() * br.height() < parent->geometry().width() * parent->geometry().height() * 0.2; 599 else if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AlwaysFullSwap) 600 doingPartialUpdate = false; 601 else if (QGLWindowSurface::swapBehavior == QGLWindowSurface::AlwaysPartialSwap) 602 doingPartialUpdate = hasPartialUpdateSupport(); 603 604 QGLContext *ctx = reinterpret_cast<QGLContext *>(parent->d_func()->extraData()->glContext); 605 if (widget != window()) { 606 if (initializeOffscreenTexture(window()->size())) 607 qWarning() << "QGLWindowSurface: Flushing to native child widget, may lead to significant performance loss"; 608 glBindTexture(target, d_ptr->tex_id); 609 610 const uint bottom = window()->height() - (br.y() + br.height()); 611 glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height()); 612 613 glBindTexture(target, 0); 614 615 ctx->makeCurrent(); 616 if (doingPartialUpdate) 617 blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), rect, br); 618 else 619 blitTexture(ctx, d_ptr->tex_id, parent->size(), window()->size(), parent->rect(), parent->rect().translated(offset + wOffset)); 620 } 621 622 if (doingPartialUpdate) 623 ctx->d_func()->swapRegion(br); 624 else 625 ctx->swapBuffers(); 626 494 627 d_ptr->paintedRegion = QRegion(); 495 context()->swapBuffers();496 628 } else { 497 629 glFlush(); … … 534 666 535 667 if (window() == parent || d_ptr->fbo->format().samples() <= 1) { 536 // glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); 668 if (ctx->d_ptr->current_fbo != 0) 669 glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0); 670 537 671 glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, d_ptr->fbo->handle()); 538 672 … … 567 701 qgl_fbo_pool()->release(temp); 568 702 } 703 704 ctx->d_ptr->current_fbo = 0; 569 705 } 570 706 #if !defined(QT_OPENGL_ES_2) … … 613 749 Q_UNUSED(target); 614 750 615 GLuint texture = d_ptr->fbo->texture();616 617 glDisable(GL_DEPTH_TEST);618 619 751 if (d_ptr->fbo->isBound()) 620 752 d_ptr->fbo->release(); 621 753 622 glViewport(0, 0, size.width(), size.height()); 623 624 QGLShaderProgram *blitProgram = 625 QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram(); 626 blitProgram->bind(); 627 blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); 628 629 // The shader manager's blit program does not multiply the 630 // vertices by the pmv matrix, so we need to do the effect 631 // of the orthographic projection here ourselves. 632 QRectF r; 633 qreal w = size.width() ? size.width() : 1.0f; 634 qreal h = size.height() ? size.height() : 1.0f; 635 r.setLeft((rect.left() / w) * 2.0f - 1.0f); 636 if (rect.right() == (size.width() - 1)) 637 r.setRight(1.0f); 638 else 639 r.setRight((rect.right() / w) * 2.0f - 1.0f); 640 r.setBottom((rect.top() / h) * 2.0f - 1.0f); 641 if (rect.bottom() == (size.height() - 1)) 642 r.setTop(1.0f); 643 else 644 r.setTop((rect.bottom() / w) * 2.0f - 1.0f); 645 646 drawTexture(r, texture, window()->size(), br); 754 blitTexture(ctx, d_ptr->fbo->texture(), size, window()->size(), rect, br); 647 755 } 648 756 #endif … … 652 760 else 653 761 glFlush(); 762 763 d_ptr->did_paint = false; 654 764 } 655 765 … … 667 777 d_ptr->geometry_updated = false; 668 778 669 670 779 QRect rect = geometry(); 671 780 hijackWindow(window()); … … 688 797 if (d_ptr->ctx) { 689 798 #ifndef QT_OPENGL_ES_2 690 if (d_ptr->destructive_swap_buffers) { 691 glBindTexture(target, d_ptr->tex_id); 692 glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 693 glBindTexture(target, 0); 694 } 799 if (d_ptr->destructive_swap_buffers) 800 initializeOffscreenTexture(rect.size()); 695 801 #endif 696 802 return; … … 772 878 773 879 #ifndef QT_OPENGL_ES_2 774 if (d_ptr->destructive_swap_buffers) { 775 glGenTextures(1, &d_ptr->tex_id); 776 glBindTexture(target, d_ptr->tex_id); 777 glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 778 779 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 780 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 781 glBindTexture(target, 0); 782 } 880 if (d_ptr->destructive_swap_buffers) 881 initializeOffscreenTexture(rect.size()); 783 882 #endif 784 883 … … 786 885 d_ptr->ctx = ctx; 787 886 d_ptr->ctx->d_ptr->internal_context = true; 887 } 888 889 bool QGLWindowSurface::initializeOffscreenTexture(const QSize &size) 890 { 891 if (size == d_ptr->textureSize) 892 return false; 893 894 glGenTextures(1, &d_ptr->tex_id); 895 glBindTexture(GL_TEXTURE_2D, d_ptr->tex_id); 896 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); 897 898 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 899 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 900 glBindTexture(GL_TEXTURE_2D, 0); 901 902 d_ptr->textureSize = size; 903 return true; 788 904 } 789 905 … … 839 955 } 840 956 841 const q_vertexType tx1 = f2vt(src.left());842 const q_vertexType tx2 = f2vt(src.right());843 const q_vertexType ty1 = f2vt(src.top());844 const q_vertexType ty2 = f2vt(src.bottom());845 846 q_vertexTypetexCoordArray[4*2] = {957 const GLfloat tx1 = src.left(); 958 const GLfloat tx2 = src.right(); 959 const GLfloat ty1 = src.top(); 960 const GLfloat ty2 = src.bottom(); 961 962 GLfloat texCoordArray[4*2] = { 847 963 tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 848 964 }; 849 965 850 q_vertexTypevertexArray[4*2];851 extern void qt_add_rect_to_array(const QRectF &r, q_vertexType*array); // qpaintengine_opengl.cpp966 GLfloat vertexArray[4*2]; 967 extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); // qpaintengine_opengl.cpp 852 968 qt_add_rect_to_array(rect, vertexArray); 853 969 854 970 #if !defined(QT_OPENGL_ES_2) 855 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);856 glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);971 glVertexPointer(2, GL_FLOAT, 0, vertexArray); 972 glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); 857 973 858 974 glBindTexture(target, tex_id);
Note:
See TracChangeset
for help on using the changeset viewer.