Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickcontext2dtexture.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
7#include <private/qquickitem_p.h>
8#include <QtQuick/private/qsgplaintexture_p.h>
10#include <QtCore/QThread>
11#include <QtGui/QGuiApplication>
12
14
15Q_LOGGING_CATEGORY(lcCanvas, "qt.quick.canvas")
16
18 : m_context(nullptr)
19 , m_surface(nullptr)
20 , m_item(nullptr)
21 , m_canvasDevicePixelRatio(1)
22 , m_canvasWindowChanged(false)
23 , m_dirtyTexture(false)
24 , m_smooth(true)
25 , m_antialiasing(false)
26 , m_tiledCanvas(false)
27 , m_painting(false)
28{
29}
30
35
45
47{
48 if (m_canvasSize != size) {
50 return true;
51 }
52 return false;
53}
54
56{
57 if (m_tileSize != size) {
59 return true;
60 }
61 return false;
62}
63
65{
66 m_smooth = smooth;
67}
68
70{
71 m_antialiasing = antialiasing;
72}
73
75{
76 m_item = item;
77 if (m_item) {
78 m_context = (QQuickContext2D*) item->rawContext(); // FIXME
80 } else {
81 m_context = nullptr;
82 }
83}
84
86{
87 bool ok = false;
88 static qreal overriddenDevicePixelRatio =
89 !qEnvironmentVariableIsEmpty("QT_CANVAS_OVERRIDE_DEVICEPIXELRATIO") ?
90 qgetenv("QT_CANVAS_OVERRIDE_DEVICEPIXELRATIO").toFloat(&ok) : 0.0;
91 qreal canvasDevicePixelRatio = overriddenDevicePixelRatio;
92 if (overriddenDevicePixelRatio == 0.0) {
93 canvasDevicePixelRatio = (m_item && m_item->window()) ?
94 m_item->window()->effectiveDevicePixelRatio() : qApp->devicePixelRatio();
95 }
96 if (!qFuzzyCompare(m_canvasDevicePixelRatio, canvasDevicePixelRatio)) {
97 qCDebug(lcCanvas, "%s device pixel ratio %.1lf -> %.1lf",
98 (m_item->objectName().isEmpty() ? "Canvas" : qPrintable(m_item->objectName())),
99 m_canvasDevicePixelRatio, canvasDevicePixelRatio);
100 m_canvasDevicePixelRatio = canvasDevicePixelRatio;
102 }
103
104 if (m_canvasWindow != r) {
107 }
108
110}
111
113{
114 bool doDirty = false;
115 if (m_tiledCanvas) {
116 for (QQuickContext2DTile* t : std::as_const(m_tiles)) {
117 bool dirty = t->rect().intersected(r).isValid();
118 t->markDirty(dirty);
119 if (dirty)
120 doDirty = true;
121 }
122 } else {
123 doDirty = m_canvasWindow.intersected(r).isValid();
124 }
125 return doDirty;
126}
127
128void QQuickContext2DTexture::canvasChanged(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing)
129{
130 QSize ts = tileSize;
131 if (ts.width() > canvasSize.width())
132 ts.setWidth(canvasSize.width());
133
134 if (ts.height() > canvasSize.height())
135 ts.setHeight(canvasSize.height());
136
137 setCanvasSize(canvasSize);
138 setTileSize(ts);
139 setCanvasWindow(canvasWindow);
140
141 if (canvasSize == canvasWindow.size()) {
142 m_tiledCanvas = false;
143 } else {
144 m_tiledCanvas = true;
145 }
146
147 if (dirtyRect.isValid())
148 setDirtyRect(dirtyRect);
149
150 setSmooth(smooth);
151 setAntialiasing(antialiasing);
152}
153
155{
156 if (!ccb || ccb->isEmpty())
157 return;
158
160 if (!device) {
161 endPainting();
162 return;
163 }
164
165 QPainter p;
166 p.begin(device);
169
170 p.setCompositionMode(QPainter::CompositionMode_SourceOver);
171
172 ccb->replay(&p, m_state, scaleFactor());
173 endPainting();
175}
176
178{
179 return m_item == nullptr;
180}
181
183{
185 if (canvasDestroyed()) {
186 delete ccb;
187 QQuickContext2D::mutex.unlock();
188 return;
189 }
190 QQuickContext2D::mutex.unlock();
191 if (!m_tiledCanvas) {
193 delete ccb;
194 return;
195 }
196
198 if (!tiledRegion.isEmpty()) {
199 QRect dirtyRect;
200 for (QQuickContext2DTile* tile : std::as_const(m_tiles)) {
201 if (tile->dirty()) {
202 if (dirtyRect.isEmpty())
203 dirtyRect = tile->rect();
204 else
205 dirtyRect |= tile->rect();
206 }
207 }
208
209 if (beginPainting()) {
211 for (QQuickContext2DTile* tile : std::as_const(m_tiles)) {
212 if (tile->dirty()) {
213 ccb->replay(tile->createPainter(m_smooth, m_antialiasing), oldState, scaleFactor());
214 tile->drawFinished();
215 tile->markDirty(false);
216 }
217 compositeTile(tile);
218 }
219 endPainting();
220 m_state = oldState;
222 }
223 }
224 delete ccb;
225}
226
228{
229 if (window.isEmpty())
230 return QRect();
231
232 const int tw = tileSize.width();
233 const int th = tileSize.height();
234 const int h1 = window.left() / tw;
235 const int v1 = window.top() / th;
236
237 const int htiles = ((window.right() - h1 * tw) + tw - 1)/tw;
238 const int vtiles = ((window.bottom() - v1 * th) + th - 1)/th;
239
240 return QRect(h1 * tw, v1 * th, htiles * tw, vtiles * th);
241}
242
244{
245 QList<QQuickContext2DTile*> oldTiles = m_tiles;
246 m_tiles.clear();
247
248 if (window.isEmpty()) {
249 return QRect();
250 }
251
253
254 const int tw = m_tileSize.width();
255 const int th = m_tileSize.height();
256 const int h1 = window.left() / tw;
257 const int v1 = window.top() / th;
258
259
260 const int htiles = r.width() / tw;
261 const int vtiles = r.height() / th;
262
263 for (int yy = 0; yy < vtiles; ++yy) {
264 for (int xx = 0; xx < htiles; ++xx) {
265 int ht = xx + h1;
266 int vt = yy + v1;
267
268 QQuickContext2DTile* tile = nullptr;
269
270 QPoint pos(ht * tw, vt * th);
272
273 for (int i = 0; i < oldTiles.size(); i++) {
274 if (oldTiles[i]->rect() == rect) {
275 tile = oldTiles.takeAt(i);
276 break;
277 }
278 }
279
280 if (!tile)
281 tile = createTile();
282
283 tile->setRect(rect);
284 m_tiles.append(tile);
285 }
286 }
287
288 qDeleteAll(oldTiles);
289
290 return r;
291}
292
298
300{
301 return ts;
302}
303
305{
306 if ((int) e->type() == QEvent::User + 1) {
307 PaintEvent *pe = static_cast<PaintEvent *>(e);
308 paint(pe->buffer);
309 return true;
310 } else if ((int) e->type() == QEvent::User + 2) {
311 CanvasChangeEvent *ce = static_cast<CanvasChangeEvent *>(e);
312 canvasChanged(ce->canvasSize, ce->tileSize, ce->canvasWindow, ce->dirtyRect, ce->smooth, ce->antialiasing);
313 return true;
314 }
315 return QObject::event(e);
316}
317
322
326
331
336
338{
339 Q_ASSERT(rf.isValid());
341 if (m_context) {
342 QImage grabbed = m_displayImage.copy(rf.toRect());
343 m_context->setGrabbedImage(grabbed);
344 }
345 QQuickContext2D::mutex.unlock();
346}
347
349{
351 m_mutex.lock();
352
353 delete last;
354
355 QSGTexture *texture = window->createTextureFromImage(m_displayImage, QQuickWindow::TextureCanUseAtlas);
356 m_dirtyTexture = false;
357
359 m_mutex.unlock();
360
361 return texture;
362}
363
365{
367
368 if (m_canvasWindow.size().isEmpty())
369 return nullptr;
370
371
375 m_image.fill(0x00000000);
376 m_canvasWindowChanged = false;
377 qCDebug(lcCanvas, "%s size %.1lf x %.1lf painting with size %d x %d DPR %.1lf",
378 (m_item->objectName().isEmpty() ? "Canvas" : qPrintable(m_item->objectName())),
379 m_item->width(), m_item->height(), m_image.size().width(), m_image.size().height(), m_canvasDevicePixelRatio);
380 }
381
382 return &m_image;
383}
384
386{
389 m_mutex.lock();
390 m_displayImage = m_image;
392 m_mutex.unlock();
393}
394
396{
397 Q_ASSERT(!tile->dirty());
400 if (target.isValid()) {
402 source.moveTo(source.topLeft() - t->rect().topLeft());
403 target.moveTo(target.topLeft() - m_canvasWindow.topLeft());
404
405 m_painter.begin(&m_image);
407 m_painter.drawImage(target, t->image(), source);
408 m_painter.end();
409 }
410}
411
413
414#include "moc_qquickcontext2dtexture_p.cpp"
IOBluetoothDevice * device
\inmodule QtCore
Definition qcoreevent.h:45
Type type() const
Returns the event type.
Definition qcoreevent.h:304
\inmodule QtGui
Definition qimage.h:37
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
QSize size() const
Returns the size of the image, i.e.
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition qimage.cpp:1758
void setDevicePixelRatio(qreal scaleFactor)
Sets the device pixel ratio for the image.
Definition qimage.cpp:1510
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
void unlock() noexcept
Unlocks the mutex.
Definition qmutex.h:289
void lock() noexcept
Locks the mutex.
Definition qmutex.h:286
QString objectName
the name of this object
Definition qobject.h:107
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
bool begin(QPaintDevice *)
Begins painting the paint device and returns true if successful; otherwise returns false.
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Draws the rectangular portion source of the given image into the target rectangle in the paint device...
@ SmoothPixmapTransform
Definition qpainter.h:54
@ Antialiasing
Definition qpainter.h:52
@ TextAntialiasing
Definition qpainter.h:53
bool end()
Ends painting.
@ CompositionMode_SourceOver
Definition qpainter.h:98
@ CompositionMode_Source
Definition qpainter.h:101
\inmodule QtCore\reentrant
Definition qpoint.h:25
QQuickContext2DTile * createTile() const override
QQuickCanvasItem::RenderTarget renderTarget() const override
void grabImage(const QRectF &region=QRectF()) override
void compositeTile(QQuickContext2DTile *tile) override
QPaintDevice * beginPainting() override
QSGTexture * textureForNextFrame(QSGTexture *lastFrame, QQuickWindow *window) override
bool event(QEvent *e) override
This virtual function receives events to an object and should return true if the event e was recogniz...
void setItem(QQuickCanvasItem *item)
virtual void compositeTile(QQuickContext2DTile *tile)=0
bool setCanvasWindow(const QRect &canvasWindow)
virtual QVector2D scaleFactor() const
QRect createTiles(const QRect &window)
void canvasChanged(const QSize &canvasSize, const QSize &tileSize, const QRect &canvasWindow, const QRect &dirtyRect, bool smooth, bool antialiasing)
virtual QQuickContext2DTile * createTile() const =0
void paint(QQuickContext2DCommandBuffer *ccb)
QQuickContext2D::State m_state
virtual QSize adjustedTileSize(const QSize &ts)
bool setCanvasSize(const QSize &size)
bool setTileSize(const QSize &size)
static QRect tiledRect(const QRectF &window, const QSize &tileSize)
void paintWithoutTiles(QQuickContext2DCommandBuffer *ccb)
void setAntialiasing(bool antialiasing)
bool setDirtyRect(const QRect &dirtyRect)
QList< QQuickContext2DTile * > m_tiles
virtual QPaintDevice * beginPainting()
void setGrabbedImage(const QImage &grab)
static QMutex mutex
QQuickWindow * window() const
Returns the window in which this item is rendered.
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
\inmodule QtCore\reentrant
Definition qrect.h:484
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:167
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
Definition qrect.h:170
QRect intersected(const QRect &other) const noexcept
Definition qrect.h:415
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:221
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:242
constexpr void moveTo(int x, int t) noexcept
Moves the rectangle, leaving the top-left corner at the given position (x, y).
Definition qrect.h:270
\inmodule QtQuick
Definition qsgtexture.h:20
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:136
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QPainter paint
qDeleteAll(list.begin(), list.end())
rect
[4]
Combined button and popup list for selecting options.
#define qApp
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
static QT_BEGIN_NAMESPACE const int tileSize
Definition qmemrotate.cpp:9
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLenum target
GLint GLfloat GLfloat v1
GLenum GLuint texture
GLsizei GLsizei GLchar * source
GLdouble GLdouble t
Definition qopenglext.h:243
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
#define v1
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
#define emit
double qreal
Definition qtypes.h:187
QGraphicsItem * item
aWidget window() -> setWindowTitle("New Window Title")
[2]