Fix subpixel positioning support
[profile/ivi/qtbase.git] / src / opengl / qglpaintdevice.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <private/qglpaintdevice_p.h>
43 #include <private/qgl_p.h>
44 #include <private/qglpixelbuffer_p.h>
45 #include <private/qglframebufferobject_p.h>
46
47 QT_BEGIN_NAMESPACE
48
49 QGLPaintDevice::QGLPaintDevice()
50     : m_thisFBO(0)
51 {
52 }
53
54 QGLPaintDevice::~QGLPaintDevice()
55 {
56 }
57
58 int QGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
59 {
60     switch(metric) {
61     case PdmWidth:
62         return size().width();
63     case PdmHeight:
64         return size().height();
65     case PdmDepth: {
66         const QGLFormat f = format();
67         return f.redBufferSize() + f.greenBufferSize() + f.blueBufferSize() + f.alphaBufferSize();
68     }
69     default:
70         qWarning("QGLPaintDevice::metric() - metric %d not known", metric);
71         return 0;
72     }
73 }
74
75 void QGLPaintDevice::beginPaint()
76 {
77     // Make sure our context is the current one:
78     QGLContext *ctx = context();
79     if (ctx != QGLContext::currentContext())
80         ctx->makeCurrent();
81
82     // Record the currently bound FBO so we can restore it again
83     // in endPaint() and bind this device's FBO
84     //
85     // Note: m_thisFBO could be zero if the paint device is not
86     // backed by an FBO (e.g. window back buffer).  But there could
87     // be a previous FBO bound to the context which we need to
88     // explicitly unbind.  Otherwise the painting will go into
89     // the previous FBO instead of to the window.
90     m_previousFBO = ctx->d_func()->current_fbo;
91
92     if (m_previousFBO != m_thisFBO) {
93         ctx->d_ptr->current_fbo = m_thisFBO;
94         glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
95     }
96
97     // Set the default fbo for the context to m_thisFBO so that
98     // if some raw GL code between beginNativePainting() and
99     // endNativePainting() calls QGLFramebufferObject::release(),
100     // painting will revert to the window surface's fbo.
101     ctx->d_ptr->default_fbo = m_thisFBO;
102 }
103
104 void QGLPaintDevice::ensureActiveTarget()
105 {
106     QGLContext* ctx = context();
107     if (ctx != QGLContext::currentContext())
108         ctx->makeCurrent();
109
110     if (ctx->d_ptr->current_fbo != m_thisFBO) {
111         ctx->d_ptr->current_fbo = m_thisFBO;
112         glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
113     }
114
115     ctx->d_ptr->default_fbo = m_thisFBO;
116 }
117
118 void QGLPaintDevice::endPaint()
119 {
120     // Make sure the FBO bound at beginPaint is re-bound again here:
121     QGLContext *ctx = context();
122     if (m_previousFBO != ctx->d_func()->current_fbo) {
123         ctx->d_ptr->current_fbo = m_previousFBO;
124         glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_previousFBO);
125     }
126
127     ctx->d_ptr->default_fbo = 0;
128 }
129
130 QGLFormat QGLPaintDevice::format() const
131 {
132     return context()->format();
133 }
134
135 bool QGLPaintDevice::alphaRequested() const
136 {
137     return context()->d_func()->reqFormat.alpha();
138 }
139
140 bool QGLPaintDevice::isFlipped() const
141 {
142     return false;
143 }
144
145 ////////////////// QGLWidgetGLPaintDevice //////////////////
146
147 QGLWidgetGLPaintDevice::QGLWidgetGLPaintDevice()
148 {
149 }
150
151 QPaintEngine* QGLWidgetGLPaintDevice::paintEngine() const
152 {
153     return glWidget->paintEngine();
154 }
155
156 void QGLWidgetGLPaintDevice::setWidget(QGLWidget* w)
157 {
158     glWidget = w;
159 }
160
161 void QGLWidgetGLPaintDevice::beginPaint()
162 {
163     QGLPaintDevice::beginPaint();
164     if (!glWidget->d_func()->disable_clear_on_painter_begin && glWidget->autoFillBackground()) {
165         if (glWidget->testAttribute(Qt::WA_TranslucentBackground))
166             glClearColor(0.0, 0.0, 0.0, 0.0);
167         else {
168             const QColor &c = glWidget->palette().brush(glWidget->backgroundRole()).color();
169             float alpha = c.alphaF();
170             glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
171         }
172         if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
173             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
174         else
175             glClear(GL_COLOR_BUFFER_BIT);
176     }
177 }
178
179 void QGLWidgetGLPaintDevice::endPaint()
180 {
181     if (glWidget->autoBufferSwap())
182         glWidget->swapBuffers();
183     QGLPaintDevice::endPaint();
184 }
185
186
187 QSize QGLWidgetGLPaintDevice::size() const
188 {
189     return glWidget->size();
190 }
191
192 QGLContext* QGLWidgetGLPaintDevice::context() const
193 {
194     return const_cast<QGLContext*>(glWidget->context());
195 }
196
197 // returns the QGLPaintDevice for the given QPaintDevice
198 QGLPaintDevice* QGLPaintDevice::getDevice(QPaintDevice* pd)
199 {
200     QGLPaintDevice* glpd = 0;
201
202     switch(pd->devType()) {
203         case QInternal::Widget:
204             // Should not be called on a non-gl widget:
205             Q_ASSERT(qobject_cast<QGLWidget*>(static_cast<QWidget*>(pd)));
206             glpd = &(static_cast<QGLWidget*>(pd)->d_func()->glDevice);
207             break;
208         case QInternal::Pbuffer:
209             glpd = &(static_cast<QGLPixelBuffer*>(pd)->d_func()->glDevice);
210             break;
211         case QInternal::FramebufferObject:
212             glpd = &(static_cast<QGLFramebufferObject*>(pd)->d_func()->glDevice);
213             break;
214         case QInternal::Pixmap: {
215             qWarning("Pixmap type not supported for GL rendering");
216             break;
217         }
218         default:
219             qWarning("QGLPaintDevice::getDevice() - Unknown device type %d", pd->devType());
220             break;
221     }
222
223     return glpd;
224 }
225
226 QT_END_NAMESPACE