Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
5**
6** This file is part of the QtOpenGL module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42
43#include <qgl.h>
44#include <qlist.h>
45#include <qmap.h>
46#include <qpixmap.h>
47#include <qevent.h>
48#include <private/qgl_p.h>
49#include <qcolormap.h>
50#include <qvarlengtharray.h>
51#include <qdebug.h>
52#include <qapplication.h>
53#include <qdesktopwidget>
54
55#include <windows.h>
56
57#include <private/qeglproperties_p.h>
58#include <private/qeglcontext_p.h>
59#include <private/qgl_egl_p.h>
60
61
62QT_BEGIN_NAMESPACE
63
64
65
66class QGLCmapPrivate
67{
68public:
69 QGLCmapPrivate() : count(1) { }
70 void ref() { ++count; }
71 bool deref() { return !--count; }
72 uint count;
73
74 enum AllocState{ UnAllocated = 0, Allocated = 0x01, Reserved = 0x02 };
75
76 int maxSize;
77 QVector<uint> colorArray;
78 QVector<quint8> allocArray;
79 QVector<quint8> contextArray;
80 QMap<uint,int> colorMap;
81};
82
83/*****************************************************************************
84 QColorMap class - temporarily here, until it is ready for prime time
85 *****************************************************************************/
86
87/****************************************************************************
88**
89** Definition of QColorMap class
90**
91****************************************************************************/
92
93#ifndef QGLCMAP_H
94#define QGLCMAP_H
95
96#include <qcolor.h>
97
98/*
99 QGLTemporaryContext implementation
100*/
101
102class QGLTemporaryContextPrivate
103{
104public:
105 QGLWidget *widget;
106};
107
108QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
109 : d(new QGLTemporaryContextPrivate)
110{
111 d->widget = new QGLWidget;
112 d->widget->makeCurrent();
113}
114
115QGLTemporaryContext::~QGLTemporaryContext()
116{
117 delete d->widget;
118}
119
120/*****************************************************************************
121 QGLFormat Win32/WGL-specific code
122 *****************************************************************************/
123
124static bool opengl32dll = false;
125
126bool QGLFormat::hasOpenGLOverlays()
127{
128 return false; // ###
129}
130
131
132bool QGLContext::chooseContext(const QGLContext* shareContext)
133{
134 Q_D(QGLContext);
135
136 // Validate the device.
137 if (!device())
138 return false;
139 int devType = device()->devType();
140 if (devType != QInternal::Pixmap && devType != QInternal::Image && devType != QInternal::Widget) {
141 qWarning("QGLContext::chooseContext(): Cannot create QGLContext's for paint device type %d", devType);
142 return false;
143 }
144
145 // Get the display and initialize it.
146 d->eglContext = new QEglContext();
147 d->ownsEglContext = true;
148 d->eglContext->setApi(QEgl::OpenGL);
149
150 // Construct the configuration we need for this surface.
151 QEglProperties configProps;
152 qt_eglproperties_set_glformat(configProps, d->glFormat);
153 configProps.setDeviceType(devType);
154 configProps.setPaintDeviceFormat(device());
155 configProps.setRenderableType(QEgl::OpenGL);
156
157 // Search for a matching configuration, reducing the complexity
158 // each time until we get something that matches.
159 if (!d->eglContext->chooseConfig(configProps)) {
160 delete d->eglContext;
161 d->eglContext = 0;
162 return false;
163 }
164
165 // Inform the higher layers about the actual format properties.
166 qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());
167
168 // Create a new context for the configuration.
169 if (!d->eglContext->createContext
170 (shareContext ? shareContext->d_func()->eglContext : 0)) {
171 delete d->eglContext;
172 d->eglContext = 0;
173 return false;
174 }
175 d->sharing = d->eglContext->isSharing();
176 if (d->sharing && shareContext)
177 const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
178
179#if defined(EGL_VERSION_1_1)
180 if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget)
181 eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
182#endif
183
184 // Create the EGL surface to draw into.
185 d->eglSurface = d->eglContext->createSurface(device());
186 if (d->eglSurface == EGL_NO_SURFACE) {
187 delete d->eglContext;
188 d->eglContext = 0;
189 return false;
190 }
191
192 return true;
193
194}
195
196
197
198static bool qLogEq(bool a, bool b)
199{
200 return (((!a) && (!b)) || (a && b));
201}
202
203int QGLContext::choosePixelFormat(void* , HDC )
204{
205
206 return 0;
207}
208
209class QGLCmapPrivate;
210
211class /*Q_EXPORT*/ QGLCmap
212{
213public:
214 enum Flags { Reserved = 0x01 };
215
216 QGLCmap(int maxSize = 256);
217 QGLCmap(const QGLCmap& map);
218 ~QGLCmap();
219
220 QGLCmap& operator=(const QGLCmap& map);
221
222 // isEmpty and/or isNull ?
223 int size() const;
224 int maxSize() const;
225
226 void resize(int newSize);
227
228 int find(QRgb color) const;
229 int findNearest(QRgb color) const;
230 int allocate(QRgb color, uint flags = 0, quint8 context = 0);
231
232 void setEntry(int idx, QRgb color, uint flags = 0, quint8 context = 0);
233
234 const QRgb* colors() const;
235
236private:
237 void detach();
238 QGLCmapPrivate* d;
239};
240
241#endif
242
243
244QGLCmap::QGLCmap(int maxSize) // add a bool prealloc?
245{
246 d = new QGLCmapPrivate;
247 d->maxSize = maxSize;
248}
249
250QGLCmap::QGLCmap(const QGLCmap& map)
251{
252 d = map.d;
253 d->ref();
254}
255
256QGLCmap::~QGLCmap()
257{
258 if (d && d->deref())
259 delete d;
260 d = 0;
261}
262
263QGLCmap& QGLCmap::operator=(const QGLCmap& map)
264{
265 map.d->ref();
266 if (d->deref())
267 delete d;
268 d = map.d;
269 return *this;
270}
271
272int QGLCmap::size() const
273{
274 return d->colorArray.size();
275}
276
277int QGLCmap::maxSize() const
278{
279 return d->maxSize;
280}
281
282void QGLCmap::detach()
283{
284 if (d->count != 1) {
285 d->deref();
286 QGLCmapPrivate* newd = new QGLCmapPrivate;
287 newd->maxSize = d->maxSize;
288 newd->colorArray = d->colorArray;
289 newd->allocArray = d->allocArray;
290 newd->contextArray = d->contextArray;
291 newd->colorArray.detach();
292 newd->allocArray.detach();
293 newd->contextArray.detach();
294 newd->colorMap = d->colorMap;
295 d = newd;
296 }
297}
298
299
300void QGLCmap::resize(int newSize)
301{
302 if (newSize < 0 || newSize > d->maxSize) {
303 qWarning("QGLCmap::resize(): size out of range");
304 return;
305 }
306 int oldSize = size();
307 detach();
308 //if shrinking; remove the lost elems from colorMap
309 d->colorArray.resize(newSize);
310 d->allocArray.resize(newSize);
311 d->contextArray.resize(newSize);
312 if (newSize > oldSize) {
313 memset(d->allocArray.data() + oldSize, 0, newSize - oldSize);
314 memset(d->contextArray.data() + oldSize, 0, newSize - oldSize);
315 }
316}
317
318
319int QGLCmap::find(QRgb color) const
320{
321 QMap<uint,int>::ConstIterator it = d->colorMap.find(color);
322 if (it != d->colorMap.end())
323 return *it;
324 return -1;
325}
326
327
328int QGLCmap::findNearest(QRgb color) const
329{
330 int idx = find(color);
331 if (idx >= 0)
332 return idx;
333 int mapSize = size();
334 int mindist = 200000;
335 int r = qRed(color);
336 int g = qGreen(color);
337 int b = qBlue(color);
338 int rx, gx, bx, dist;
339 for (int i=0; i < mapSize; i++) {
340 if (!(d->allocArray[i] & QGLCmapPrivate::Allocated))
341 continue;
342 QRgb ci = d->colorArray[i];
343 rx = r - qRed(ci);
344 gx = g - qGreen(ci);
345 bx = b - qBlue(ci);
346 dist = rx*rx + gx*gx + bx*bx; // calculate distance
347 if (dist < mindist) { // minimal?
348 mindist = dist;
349 idx = i;
350 }
351 }
352 return idx;
353}
354
355
356// Does not always allocate; returns existing c idx if found
357
358int QGLCmap::allocate(QRgb color, uint flags, quint8 context)
359{
360 int idx = find(color);
361 if (idx >= 0)
362 return idx;
363
364 int mapSize = d->colorArray.size();
365 int newIdx = d->allocArray.indexOf(QGLCmapPrivate::UnAllocated);
366
367 if (newIdx < 0) { // Must allocate more room
368 if (mapSize < d->maxSize) {
369 newIdx = mapSize;
370 mapSize++;
371 resize(mapSize);
372 }
373 else {
374 //# add a bool param that says what to do in case no more room -
375 // fail (-1) or return nearest?
376 return -1;
377 }
378 }
379
380 d->colorArray[newIdx] = color;
381 if (flags & QGLCmap::Reserved) {
382 d->allocArray[newIdx] = QGLCmapPrivate::Reserved;
383 }
384 else {
385 d->allocArray[newIdx] = QGLCmapPrivate::Allocated;
386 d->colorMap.insert(color, newIdx);
387 }
388 d->contextArray[newIdx] = context;
389 return newIdx;
390}
391
392
393void QGLCmap::setEntry(int idx, QRgb color, uint flags, quint8 context)
394{
395 if (idx < 0 || idx >= d->maxSize) {
396 qWarning("QGLCmap::set(): Index out of range");
397 return;
398 }
399 detach();
400 int mapSize = size();
401 if (idx >= mapSize) {
402 mapSize = idx + 1;
403 resize(mapSize);
404 }
405 d->colorArray[idx] = color;
406 if (flags & QGLCmap::Reserved) {
407 d->allocArray[idx] = QGLCmapPrivate::Reserved;
408 }
409 else {
410 d->allocArray[idx] = QGLCmapPrivate::Allocated;
411 d->colorMap.insert(color, idx);
412 }
413 d->contextArray[idx] = context;
414}
415
416
417const QRgb* QGLCmap::colors() const
418{
419 return d->colorArray.data();
420}
421
422
423/*****************************************************************************
424 QGLWidget Win32/WGL-specific code
425 *****************************************************************************/
426
427void QGLWidgetPrivate::init(QGLContext *ctx, const QGLWidget* shareWidget)
428{
429 Q_Q(QGLWidget);
430 olcx = 0;
431 initContext(ctx, shareWidget);
432
433 if (q->isValid() && q->context()->format().hasOverlay()) {
434 olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), q);
435 if (!olcx->create(shareWidget ? shareWidget->overlayContext() : 0)) {
436 delete olcx;
437 olcx = 0;
438 glcx->d_func()->glFormat.setOverlay(false);
439 }
440 } else {
441 olcx = 0;
442 }
443}
444
445/*\internal
446 Store color values in the given colormap.
447*/
448static void qStoreColors(HPALETTE cmap, const QGLColormap & cols)
449{
450 QRgb color;
451 PALETTEENTRY pe;
452
453 for (int i = 0; i < cols.size(); i++) {
454 color = cols.entryRgb(i);
455 pe.peRed = qRed(color);
456 pe.peGreen = qGreen(color);
457 pe.peBlue = qBlue(color);
458 pe.peFlags = 0;
459
460 SetPaletteEntries(cmap, i, 1, &pe);
461 }
462}
463
464void QGLWidgetPrivate::updateColormap()
465{
466 Q_Q(QGLWidget);
467 if (!cmap.handle())
468 return;
469 HDC hdc = GetDC(q->winId());
470 SelectPalette(hdc, (HPALETTE) cmap.handle(), TRUE);
471 qStoreColors((HPALETTE) cmap.handle(), cmap);
472 RealizePalette(hdc);
473 ReleaseDC(q->winId(), hdc);
474}
475
476bool QGLWidget::event(QEvent *e)
477{
478 Q_D(QGLWidget);
479 if (e->type() == QEvent::ParentChange) {
480 setContext(new QGLContext(d->glcx->requestedFormat(), this));
481 // the overlay needs to be recreated as well
482 delete d->olcx;
483 if (isValid() && context()->format().hasOverlay()) {
484 d->olcx = new QGLContext(QGLFormat::defaultOverlayFormat(), this);
485 if (!d->olcx->create(isSharing() ? d->glcx : 0)) {
486 delete d->olcx;
487 d->olcx = 0;
488 d->glcx->d_func()->glFormat.setOverlay(false);
489 }
490 } else {
491 d->olcx = 0;
492 }
493 } else if (e->type() == QEvent::Show && !format().rgba()) {
494 d->updateColormap();
495 }
496
497 return QWidget::event(e);
498}
499
500
501void QGLWidget::resizeEvent(QResizeEvent *)
502{
503 Q_D(QGLWidget);
504 if (!isValid())
505 return;
506 makeCurrent();
507 if (!d->glcx->initialized())
508 glInit();
509 resizeGL(width(), height());
510 if (d->olcx) {
511 makeOverlayCurrent();
512 resizeOverlayGL(width(), height());
513 }
514}
515
516
517const QGLContext* QGLWidget::overlayContext() const
518{
519 return d_func()->olcx;
520}
521
522
523void QGLWidget::makeOverlayCurrent()
524{
525 Q_D(QGLWidget);
526 if (d->olcx) {
527 d->olcx->makeCurrent();
528 if (!d->olcx->initialized()) {
529 initializeOverlayGL();
530 d->olcx->setInitialized(true);
531 }
532 }
533}
534
535
536void QGLWidget::updateOverlayGL()
537{
538 Q_D(QGLWidget);
539 if (d->olcx) {
540 makeOverlayCurrent();
541 paintOverlayGL();
542 if (d->olcx->format().doubleBuffer()) {
543 if (d->autoSwap)
544 d->olcx->swapBuffers();
545 }
546 else {
547 glFlush();
548 }
549 }
550}
551
552void QGLWidget::setContext(QGLContext *context,
553 const QGLContext* shareContext,
554 bool deleteOldContext)
555{
556 Q_D(QGLWidget);
557 if (context == 0) {
558 qWarning("QGLWidget::setContext: Cannot set null context");
559 return;
560 }
561 if (!context->deviceIsPixmap() && context->device() != this) {
562 qWarning("QGLWidget::setContext: Context must refer to this widget");
563 return;
564 }
565
566 if (d->glcx)
567 d->glcx->doneCurrent();
568 QGLContext* oldcx = d->glcx;
569 d->glcx = context;
570
571 bool doShow = false;
572 if (oldcx && oldcx->d_func()->win == winId() && !d->glcx->deviceIsPixmap()) {
573 // We already have a context and must therefore create a new
574 // window since Windows does not permit setting a new OpenGL
575 // context for a window that already has one set.
576 doShow = isVisible();
577 QWidget *pW = static_cast<QWidget *>(parent());
578 QPoint pos = geometry().topLeft();
579 setParent(pW, windowFlags());
580 move(pos);
581 }
582
583 if (!d->glcx->isValid()) {
584 d->glcx->create(shareContext ? shareContext : oldcx);
585 // the above is a trick to keep disp lists etc when a
586 // QGLWidget has been reparented, so remove the sharing
587 // flag if we don't actually have a sharing context.
588 if (!shareContext)
589 d->glcx->d_ptr->sharing = false;
590 }
591
592 if (deleteOldContext)
593 delete oldcx;
594
595 if (doShow)
596 show();
597}
598
599
600void QGLWidgetPrivate::cleanupColormaps()
601{
602 Q_Q(QGLWidget);
603 if (cmap.handle()) {
604 HDC hdc = GetDC(q->winId());
605 SelectPalette(hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), FALSE);
606 DeleteObject((HPALETTE) cmap.handle());
607 ReleaseDC(q->winId(), hdc);
608 cmap.setHandle(0);
609 }
610 return;
611}
612
613const QGLColormap & QGLWidget::colormap() const
614{
615 return d_func()->cmap;
616}
617
618void QGLWidget::setColormap(const QGLColormap & c)
619{
620 Q_D(QGLWidget);
621 d->cmap = c;
622
623 if (d->cmap.handle()) { // already have an allocated cmap
624 d->updateColormap();
625 } else {
626 LOGPALETTE *lpal = (LOGPALETTE *) malloc(sizeof(LOGPALETTE)
627 +c.size()*sizeof(PALETTEENTRY));
628 lpal->palVersion = 0x300;
629 lpal->palNumEntries = c.size();
630 d->cmap.setHandle(CreatePalette(lpal));
631 free(lpal);
632 d->updateColormap();
633 }
634}
635
636QT_END_NAMESPACE
637

Warning: That file was not part of the compilation database. It may have many parsing errors.