~ubuntu-branches/ubuntu/trusty/virtualbox-ose/trusty

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 * VBoxFBOverlay implementaion
 
3
 */
 
4
 
 
5
/*
 
6
 * Copyright (C) 2009 Sun Microsystems, Inc.
 
7
 *
 
8
 * This file is part of VirtualBox Open Source Edition (OSE), as
 
9
 * available from http://www.virtualbox.org. This file is free software;
 
10
 * you can redistribute it and/or modify it under the terms of the GNU
 
11
 * General Public License (GPL) as published by the Free Software
 
12
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 
13
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 
14
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 
15
 *
 
16
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 
17
 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 
18
 * additional information or have any questions.
 
19
 */
 
20
#if defined (VBOX_GUI_USE_QGL)
 
21
 
 
22
#define LOG_GROUP LOG_GROUP_GUI
 
23
 
 
24
#include "VBoxFBOverlay.h"
 
25
#include "VBoxFrameBuffer.h"
 
26
 
 
27
#include "VBoxConsoleView.h"
 
28
#include "VBoxProblemReporter.h"
 
29
#include "VBoxGlobal.h"
 
30
 
 
31
#include <VBox/VBoxGL2D.h>
 
32
 
 
33
/* Qt includes */
 
34
#include <QGLWidget>
 
35
 
 
36
#include <iprt/asm.h>
 
37
 
 
38
#ifdef VBOX_WITH_VIDEOHWACCEL
 
39
#include <VBox/VBoxVideo.h>
 
40
#include <VBox/types.h>
 
41
#include <VBox/ssm.h>
 
42
#endif
 
43
#include <iprt/semaphore.h>
 
44
 
 
45
#include <QFile>
 
46
#include <QTextStream>
 
47
 
 
48
#ifdef VBOXQGL_PROF_BASE
 
49
# ifdef VBOXQGL_DBG_SURF
 
50
#  define VBOXQGL_PROF_WIDTH 1400
 
51
#  define VBOXQGL_PROF_HEIGHT 1050
 
52
# else
 
53
# define VBOXQGL_PROF_WIDTH 1400
 
54
# define VBOXQGL_PROF_HEIGHT 1050
 
55
//#define VBOXQGL_PROF_WIDTH 720
 
56
//#define VBOXQGL_PROF_HEIGHT 480
 
57
# endif
 
58
#endif
 
59
 
 
60
#define VBOXQGL_STATE_NAMEBASE "QGLVHWAData"
 
61
#define VBOXQGL_STATE_VERSION 2
 
62
 
 
63
#ifdef DEBUG
 
64
VBoxVHWADbgTimer::VBoxVHWADbgTimer(uint32_t cPeriods) :
 
65
        mPeriodSum(0LL),
 
66
        mPrevTime(0LL),
 
67
        mcFrames(0LL),
 
68
        mcPeriods(cPeriods),
 
69
        miPeriod(0)
 
70
{
 
71
    mpaPeriods = new uint64_t[cPeriods];
 
72
    memset(mpaPeriods, 0, cPeriods * sizeof(mpaPeriods[0]));
 
73
}
 
74
 
 
75
VBoxVHWADbgTimer::~VBoxVHWADbgTimer()
 
76
{
 
77
    delete[] mpaPeriods;
 
78
}
 
79
 
 
80
void VBoxVHWADbgTimer::frame()
 
81
{
 
82
    uint64_t cur = VBOXGETTIME();
 
83
    if(mPrevTime)
 
84
    {
 
85
        uint64_t curPeriod = cur - mPrevTime;
 
86
        mPeriodSum += curPeriod - mpaPeriods[miPeriod];
 
87
        mpaPeriods[miPeriod] = curPeriod;
 
88
        ++miPeriod;
 
89
        miPeriod %= mcPeriods;
 
90
    }
 
91
    mPrevTime = cur;
 
92
    ++mcFrames;
 
93
}
 
94
#endif
 
95
 
 
96
//#define VBOXQGLOVERLAY_STATE_NAMEBASE "QGLOverlayVHWAData"
 
97
//#define VBOXQGLOVERLAY_STATE_VERSION 1
 
98
 
 
99
#ifdef DEBUG_misha
 
100
# define VBOXQGL_STATE_DEBUG
 
101
#endif
 
102
 
 
103
#ifdef VBOXQGL_STATE_DEBUG
 
104
#define VBOXQGL_STATE_START_MAGIC        0x12345678
 
105
#define VBOXQGL_STATE_STOP_MAGIC         0x87654321
 
106
 
 
107
#define VBOXQGL_STATE_SURFSTART_MAGIC    0x9abcdef1
 
108
#define VBOXQGL_STATE_SURFSTOP_MAGIC     0x1fedcba9
 
109
 
 
110
#define VBOXQGL_STATE_OVERLAYSTART_MAGIC 0x13579bdf
 
111
#define VBOXQGL_STATE_OVERLAYSTOP_MAGIC  0xfdb97531
 
112
 
 
113
#define VBOXQGL_SAVE_START(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_START_MAGIC); AssertRC(rc);}while(0)
 
114
#define VBOXQGL_SAVE_STOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_STOP_MAGIC); AssertRC(rc);}while(0)
 
115
 
 
116
#define VBOXQGL_SAVE_SURFSTART(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_SURFSTART_MAGIC); AssertRC(rc);}while(0)
 
117
#define VBOXQGL_SAVE_SURFSTOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_SURFSTOP_MAGIC); AssertRC(rc);}while(0)
 
118
 
 
119
#define VBOXQGL_SAVE_OVERLAYSTART(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_OVERLAYSTART_MAGIC); AssertRC(rc);}while(0)
 
120
#define VBOXQGL_SAVE_OVERLAYSTOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_OVERLAYSTOP_MAGIC); AssertRC(rc);}while(0)
 
121
 
 
122
#define VBOXQGL_LOAD_CHECK(_pSSM, _v) \
 
123
    do{ \
 
124
        uint32_t _u32; \
 
125
        int rc = SSMR3GetU32(_pSSM, &_u32); AssertRC(rc); \
 
126
        if(_u32 != (_v)) \
 
127
        { \
 
128
            VBOXQGLLOG(("load error: expected magic (0x%x), but was (0x%x)\n", (_v), _u32));\
 
129
        }\
 
130
        Assert(_u32 == (_v)); \
 
131
    }while(0)
 
132
 
 
133
#define VBOXQGL_LOAD_START(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_START_MAGIC)
 
134
#define VBOXQGL_LOAD_STOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_STOP_MAGIC)
 
135
 
 
136
#define VBOXQGL_LOAD_SURFSTART(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_SURFSTART_MAGIC)
 
137
#define VBOXQGL_LOAD_SURFSTOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_SURFSTOP_MAGIC)
 
138
 
 
139
#define VBOXQGL_LOAD_OVERLAYSTART(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_OVERLAYSTART_MAGIC)
 
140
#define VBOXQGL_LOAD_OVERLAYSTOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_OVERLAYSTOP_MAGIC)
 
141
 
 
142
#else
 
143
 
 
144
#define VBOXQGL_SAVE_START(_pSSM) do{}while(0)
 
145
#define VBOXQGL_SAVE_STOP(_pSSM) do{}while(0)
 
146
 
 
147
#define VBOXQGL_SAVE_SURFSTART(_pSSM) do{}while(0)
 
148
#define VBOXQGL_SAVE_SURFSTOP(_pSSM) do{}while(0)
 
149
 
 
150
#define VBOXQGL_SAVE_OVERLAYSTART(_pSSM) do{}while(0)
 
151
#define VBOXQGL_SAVE_OVERLAYSTOP(_pSSM) do{}while(0)
 
152
 
 
153
#define VBOXQGL_LOAD_START(_pSSM) do{}while(0)
 
154
#define VBOXQGL_LOAD_STOP(_pSSM) do{}while(0)
 
155
 
 
156
#define VBOXQGL_LOAD_SURFSTART(_pSSM) do{}while(0)
 
157
#define VBOXQGL_LOAD_SURFSTOP(_pSSM) do{}while(0)
 
158
 
 
159
#define VBOXQGL_LOAD_OVERLAYSTART(_pSSM) do{}while(0)
 
160
#define VBOXQGL_LOAD_OVERLAYSTOP(_pSSM) do{}while(0)
 
161
 
 
162
#endif
 
163
 
 
164
static VBoxVHWAInfo g_VBoxVHWASupportInfo;
 
165
static bool g_bVBoxVHWAChecked = false;
 
166
static bool g_bVBoxVHWASupported = false;
 
167
 
 
168
static struct _VBOXVHWACMD * vhwaHHCmdCreate(VBOXVHWACMD_TYPE type, size_t size)
 
169
{
 
170
    char *buf = (char*)malloc(VBOXVHWACMD_SIZE_FROMBODYSIZE(size));
 
171
    memset(buf, 0, size);
 
172
    VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
 
173
    pCmd->enmCmd = type;
 
174
    pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
 
175
    return pCmd;
 
176
}
 
177
 
 
178
static const VBoxVHWAInfo & vboxVHWAGetSupportInfo(const QGLContext *pContext)
 
179
{
 
180
    if(!g_VBoxVHWASupportInfo.isInitialized())
 
181
    {
 
182
        if(pContext)
 
183
        {
 
184
            g_VBoxVHWASupportInfo.init(pContext);
 
185
        }
 
186
        else
 
187
        {
 
188
            VBoxGLTmpContext ctx;
 
189
            const QGLContext *pContext = ctx.makeCurrent();
 
190
            Assert(pContext);
 
191
            if(pContext)
 
192
            {
 
193
                g_VBoxVHWASupportInfo.init(pContext);
 
194
            }
 
195
        }
 
196
    }
 
197
    return g_VBoxVHWASupportInfo;
 
198
}
 
199
 
 
200
class VBoxVHWACommandProcessEvent : public QEvent
 
201
{
 
202
public:
 
203
    VBoxVHWACommandProcessEvent (VBoxVHWACommandElement *pEl)
 
204
        : QEvent ((QEvent::Type) VBoxDefs::VHWACommandProcessType)
 
205
    {
 
206
        mCmdPipe.put(pEl);
 
207
    }
 
208
    VBoxVHWACommandElementPipe & pipe() { return mCmdPipe; }
 
209
 
 
210
    VBoxVHWACommandProcessEvent *mpNext;
 
211
private:
 
212
    VBoxVHWACommandElementPipe mCmdPipe;
 
213
};
 
214
 
 
215
 
 
216
 
 
217
VBoxVHWAHandleTable::VBoxVHWAHandleTable(uint32_t initialSize)
 
218
{
 
219
    mTable = new void*[initialSize];
 
220
    memset(mTable, 0, initialSize*sizeof(void*));
 
221
    mcSize = initialSize;
 
222
    mcUsage = 0;
 
223
    mCursor = 1; /* 0 is treated as invalid */
 
224
}
 
225
 
 
226
VBoxVHWAHandleTable::~VBoxVHWAHandleTable()
 
227
{
 
228
    delete[] mTable;
 
229
}
 
230
 
 
231
uint32_t VBoxVHWAHandleTable::put(void * data)
 
232
{
 
233
    Assert(data);
 
234
    if(!data)
 
235
        return VBOXVHWA_SURFHANDLE_INVALID;
 
236
 
 
237
    if(mcUsage == mcSize)
 
238
    {
 
239
        /* @todo: resize */
 
240
        Assert(0);
 
241
    }
 
242
 
 
243
    Assert(mcUsage < mcSize);
 
244
    if(mcUsage >= mcSize)
 
245
        return VBOXVHWA_SURFHANDLE_INVALID;
 
246
 
 
247
    for(int k = 0; k < 2; ++k)
 
248
    {
 
249
        Assert(mCursor != 0);
 
250
        for(uint32_t i = mCursor; i < mcSize; ++i)
 
251
        {
 
252
            if(!mTable[i])
 
253
            {
 
254
                doPut(i, data);
 
255
                mCursor = i+1;
 
256
                return i;
 
257
            }
 
258
        }
 
259
        mCursor = 1; /* 0 is treated as invalid */
 
260
    }
 
261
 
 
262
    Assert(0);
 
263
    return VBOXVHWA_SURFHANDLE_INVALID;
 
264
}
 
265
 
 
266
bool VBoxVHWAHandleTable::mapPut(uint32_t h, void * data)
 
267
{
 
268
    if(mcSize <= h)
 
269
        return false;
 
270
    if(h == 0)
 
271
        return false;
 
272
    if(mTable[h])
 
273
        return false;
 
274
 
 
275
    doPut(h, data);
 
276
    return true;
 
277
}
 
278
 
 
279
void* VBoxVHWAHandleTable::get(uint32_t h)
 
280
{
 
281
    Assert(h < mcSize);
 
282
    Assert(h > 0);
 
283
    return mTable[h];
 
284
}
 
285
 
 
286
void* VBoxVHWAHandleTable::remove(uint32_t h)
 
287
{
 
288
    Assert(mcUsage);
 
289
    Assert(h < mcSize);
 
290
    void* val = mTable[h];
 
291
    Assert(val);
 
292
    if(val)
 
293
    {
 
294
        doRemove(h);
 
295
    }
 
296
    return val;
 
297
}
 
298
 
 
299
void VBoxVHWAHandleTable::doPut(uint32_t h, void * data)
 
300
{
 
301
    ++mcUsage;
 
302
    mTable[h] = data;
 
303
}
 
304
 
 
305
void VBoxVHWAHandleTable::doRemove(uint32_t h)
 
306
{
 
307
    mTable[h] = 0;
 
308
    --mcUsage;
 
309
}
 
310
 
 
311
static VBoxVHWATexture* vboxVHWATextureCreate(const QGLContext * pContext, const QRect & aRect, const VBoxVHWAColorFormat & aFormat, bool bVGA)
 
312
{
 
313
    const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(pContext);
 
314
 
 
315
    if(!bVGA && info.getGlInfo().isPBOSupported())
 
316
    {
 
317
        VBOXQGLLOG(("VBoxVHWATextureNP2RectPBO\n"));
 
318
        return new VBoxVHWATextureNP2RectPBO(aRect, aFormat);
 
319
    }
 
320
    else if(info.getGlInfo().isTextureRectangleSupported())
 
321
    {
 
322
        VBOXQGLLOG(("VBoxVHWATextureNP2Rect\n"));
 
323
        return new VBoxVHWATextureNP2Rect(aRect, aFormat);
 
324
    }
 
325
    else if(info.getGlInfo().isTextureNP2Supported())
 
326
    {
 
327
        VBOXQGLLOG(("VBoxVHWATextureNP2\n"));
 
328
        return new VBoxVHWATextureNP2(aRect, aFormat);
 
329
    }
 
330
    VBOXQGLLOG(("VBoxVHWATexture\n"));
 
331
    return new VBoxVHWATexture(aRect, aFormat);
 
332
}
 
333
 
 
334
class VBoxVHWAGlShaderComponent
 
335
{
 
336
public:
 
337
    VBoxVHWAGlShaderComponent(const char *aRcName, GLenum aType) :
 
338
        mRcName(aRcName),
 
339
        mType(aType),
 
340
        mInitialized(false)
 
341
    {}
 
342
 
 
343
//    virtual ~VBoxVHWAGlShaderComponent();
 
344
 
 
345
 
 
346
    int init();
 
347
//    virtual int initUniforms(class VBoxVHWAGlProgram * pProgram){}
 
348
//    void uninit();
 
349
 
 
350
    const char * contents() { return mSource.constData(); }
 
351
    bool isInitialized() { return mInitialized; }
 
352
private:
 
353
    const char *mRcName;
 
354
    GLenum mType;
 
355
    QByteArray mSource;
 
356
    bool mInitialized;
 
357
};
 
358
 
 
359
int VBoxVHWAGlShaderComponent::init()
 
360
{
 
361
//    Assert(!isInitialized());
 
362
    if(isInitialized())
 
363
        return VINF_ALREADY_INITIALIZED;
 
364
 
 
365
    QFile fi(mRcName);
 
366
    if (!fi.open(QIODevice::ReadOnly))
 
367
    {
 
368
        Assert(0);
 
369
        return VERR_GENERAL_FAILURE;
 
370
    }
 
371
 
 
372
    QTextStream is(&fi);
 
373
    QString program = is.readAll();
 
374
 
 
375
    mSource = program.toAscii();
 
376
 
 
377
    mInitialized = true;
 
378
    return VINF_SUCCESS;
 
379
}
 
380
 
 
381
class VBoxVHWAGlShader
 
382
{
 
383
public:
 
384
    VBoxVHWAGlShader() :
 
385
        mType(GL_FRAGMENT_SHADER),
 
386
        mcComponents(0)
 
387
    {}
 
388
 
 
389
    VBoxVHWAGlShader & operator= (const VBoxVHWAGlShader & other)
 
390
    {
 
391
        mcComponents = other.mcComponents;
 
392
        mType = other.mType;
 
393
        if(mcComponents)
 
394
        {
 
395
            maComponents = new VBoxVHWAGlShaderComponent*[mcComponents];
 
396
            memcpy(maComponents, other.maComponents, mcComponents * sizeof(maComponents[0]));
 
397
        }
 
398
        return *this;
 
399
    }
 
400
 
 
401
    VBoxVHWAGlShader(const VBoxVHWAGlShader & other)
 
402
    {
 
403
        mcComponents = other.mcComponents;
 
404
        mType = other.mType;
 
405
        if(mcComponents)
 
406
        {
 
407
            maComponents = new VBoxVHWAGlShaderComponent*[mcComponents];
 
408
            memcpy(maComponents, other.maComponents, mcComponents * sizeof(maComponents[0]));
 
409
        }
 
410
    }
 
411
 
 
412
    VBoxVHWAGlShader(GLenum aType, VBoxVHWAGlShaderComponent ** aComponents, int cComponents)
 
413
        : mType(aType)
 
414
    {
 
415
        maComponents = new VBoxVHWAGlShaderComponent*[cComponents];
 
416
        mcComponents = cComponents;
 
417
        memcpy(maComponents, aComponents, cComponents * sizeof(maComponents[0]));
 
418
    }
 
419
 
 
420
    ~VBoxVHWAGlShader() {delete[] maComponents;}
 
421
    int init();
 
422
    GLenum type() { return mType; }
 
423
    GLuint shader() { return mShader; }
 
424
private:
 
425
    GLenum mType;
 
426
    GLuint mShader;
 
427
    VBoxVHWAGlShaderComponent ** maComponents;
 
428
    int mcComponents;
 
429
};
 
430
 
 
431
int VBoxVHWAGlShader::init()
 
432
{
 
433
    int rc;
 
434
    GLint *length;
 
435
    const char **sources;
 
436
    length = new GLint[mcComponents];
 
437
    sources = new const char*[mcComponents];
 
438
    for(int i = 0; i < mcComponents; i++)
 
439
    {
 
440
        length[i] = -1;
 
441
        rc = maComponents[i]->init();
 
442
        Assert(RT_SUCCESS(rc));
 
443
        if(RT_FAILURE(rc))
 
444
            return rc;
 
445
        sources[i] = maComponents[i]->contents();
 
446
    }
 
447
 
 
448
#ifdef DEBUG
 
449
    VBOXQGLLOG(("\ncompiling shaders:\n------------\n"));
 
450
    for(int i = 0; i < mcComponents; i++)
 
451
    {
 
452
        VBOXQGLLOG(("**********\n%s\n***********\n", sources[i]));
 
453
    }
 
454
    VBOXQGLLOG(("------------\n"));
 
455
#endif
 
456
    mShader = vboxglCreateShader(mType);
 
457
 
 
458
    VBOXQGL_CHECKERR(
 
459
            vboxglShaderSource(mShader, mcComponents, sources, length);
 
460
            );
 
461
 
 
462
    VBOXQGL_CHECKERR(
 
463
            vboxglCompileShader(mShader);
 
464
            );
 
465
 
 
466
    GLint compiled;
 
467
    VBOXQGL_CHECKERR(
 
468
            vboxglGetShaderiv(mShader, GL_COMPILE_STATUS, &compiled);
 
469
            );
 
470
 
 
471
#ifdef DEBUG
 
472
    GLchar * pBuf = new GLchar[16300];
 
473
    vboxglGetShaderInfoLog(mShader, 16300, NULL, pBuf);
 
474
    VBOXQGLLOG(("\ncompile log:\n-----------\n%s\n---------\n", pBuf));
 
475
    delete pBuf;
 
476
#endif
 
477
 
 
478
    Assert(compiled);
 
479
    if(compiled)
 
480
    {
 
481
        return VINF_SUCCESS;
 
482
    }
 
483
 
 
484
 
 
485
    VBOXQGL_CHECKERR(
 
486
            vboxglDeleteShader(mShader);
 
487
            );
 
488
    mShader = 0;
 
489
 
 
490
    delete[] length;
 
491
    delete[] sources;
 
492
    return VERR_GENERAL_FAILURE;
 
493
}
 
494
 
 
495
class VBoxVHWAGlProgram
 
496
{
 
497
public:
 
498
    VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders);
 
499
 
 
500
    ~VBoxVHWAGlProgram();
 
501
 
 
502
    virtual int init();
 
503
    virtual void uninit();
 
504
    virtual int start();
 
505
    virtual int stop();
 
506
    bool isInitialized() { return mProgram; }
 
507
    GLuint program() {return mProgram;}
 
508
private:
 
509
    GLuint mProgram;
 
510
    VBoxVHWAGlShader *mShaders;
 
511
    int mcShaders;
 
512
};
 
513
 
 
514
VBoxVHWAGlProgram::VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders) :
 
515
       mProgram(0),
 
516
       mcShaders(0)
 
517
{
 
518
    Assert(acShaders);
 
519
    if(acShaders)
 
520
    {
 
521
        mShaders = new VBoxVHWAGlShader[acShaders];
 
522
        for(int i = 0; i < acShaders; i++)
 
523
        {
 
524
            mShaders[i] = *apShaders[i];
 
525
        }
 
526
        mcShaders = acShaders;
 
527
    }
 
528
}
 
529
 
 
530
VBoxVHWAGlProgram::~VBoxVHWAGlProgram()
 
531
{
 
532
    uninit();
 
533
 
 
534
    if(mShaders)
 
535
    {
 
536
        delete[] mShaders;
 
537
    }
 
538
}
 
539
 
 
540
int VBoxVHWAGlProgram::init()
 
541
{
 
542
    Assert(!isInitialized());
 
543
    if(isInitialized())
 
544
        return VINF_ALREADY_INITIALIZED;
 
545
 
 
546
    Assert(mcShaders);
 
547
    if(!mcShaders)
 
548
        return VERR_GENERAL_FAILURE;
 
549
 
 
550
    int rc = VINF_SUCCESS;
 
551
    for(int i = 0; i < mcShaders; i++)
 
552
    {
 
553
        int rc = mShaders[i].init();
 
554
        Assert(RT_SUCCESS(rc));
 
555
        if(RT_FAILURE(rc))
 
556
        {
 
557
            break;
 
558
        }
 
559
    }
 
560
    if(RT_FAILURE(rc))
 
561
    {
 
562
        return rc;
 
563
    }
 
564
 
 
565
    mProgram = vboxglCreateProgram();
 
566
    Assert(mProgram);
 
567
    if(mProgram)
 
568
    {
 
569
        for(int i = 0; i < mcShaders; i++)
 
570
        {
 
571
            VBOXQGL_CHECKERR(
 
572
                    vboxglAttachShader(mProgram, mShaders[i].shader());
 
573
                    );
 
574
        }
 
575
 
 
576
        VBOXQGL_CHECKERR(
 
577
                vboxglLinkProgram(mProgram);
 
578
                );
 
579
 
 
580
 
 
581
        GLint linked;
 
582
        vboxglGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
 
583
 
 
584
#ifdef DEBUG
 
585
        GLchar * pBuf = new GLchar[16300];
 
586
        vboxglGetProgramInfoLog(mProgram, 16300, NULL, pBuf);
 
587
        VBOXQGLLOG(("link log: %s\n", pBuf));
 
588
        Assert(linked);
 
589
        delete pBuf;
 
590
#endif
 
591
 
 
592
        if(linked)
 
593
        {
 
594
            return VINF_SUCCESS;
 
595
        }
 
596
 
 
597
        VBOXQGL_CHECKERR(
 
598
                vboxglDeleteProgram(mProgram);
 
599
                );
 
600
        mProgram = 0;
 
601
    }
 
602
    return VERR_GENERAL_FAILURE;
 
603
}
 
604
 
 
605
void VBoxVHWAGlProgram::uninit()
 
606
{
 
607
    if(!isInitialized())
 
608
        return;
 
609
 
 
610
    VBOXQGL_CHECKERR(
 
611
            vboxglDeleteProgram(mProgram);
 
612
            );
 
613
    mProgram = 0;
 
614
}
 
615
 
 
616
int VBoxVHWAGlProgram::start()
 
617
{
 
618
    VBOXQGL_CHECKERR(
 
619
            vboxglUseProgram(mProgram);
 
620
            );
 
621
    return VINF_SUCCESS;
 
622
}
 
623
 
 
624
int VBoxVHWAGlProgram::stop()
 
625
{
 
626
    VBOXQGL_CHECKERR(
 
627
            vboxglUseProgram(0);
 
628
            );
 
629
    return VINF_SUCCESS;
 
630
}
 
631
 
 
632
#define VBOXVHWA_PROGRAM_DSTCOLORKEY        0x00000001
 
633
#define VBOXVHWA_PROGRAM_SRCCOLORKEY        0x00000002
 
634
#define VBOXVHWA_PROGRAM_COLORCONV          0x00000004
 
635
#define VBOXVHWA_PROGRAM_COLORKEYNODISCARD  0x00000008
 
636
 
 
637
#define VBOXVHWA_SUPPORTED_PROGRAM ( \
 
638
        VBOXVHWA_PROGRAM_DSTCOLORKEY \
 
639
        | VBOXVHWA_PROGRAM_SRCCOLORKEY \
 
640
        | VBOXVHWA_PROGRAM_COLORCONV \
 
641
        | VBOXVHWA_PROGRAM_COLORKEYNODISCARD \
 
642
        )
 
643
 
 
644
class VBoxVHWAGlProgramVHWA : public VBoxVHWAGlProgram
 
645
{
 
646
public:
 
647
    VBoxVHWAGlProgramVHWA(/*class VBoxVHWAGlProgramMngr *aMngr, */uint32_t type, uint32_t fourcc, VBoxVHWAGlShader ** apShaders, int acShaders);
 
648
 
 
649
    uint32_t type() const {return mType;}
 
650
    uint32_t fourcc() const {return mFourcc;}
 
651
 
 
652
    int setDstCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b);
 
653
 
 
654
    int setDstCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b);
 
655
 
 
656
    int setSrcCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b);
 
657
 
 
658
    int setSrcCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b);
 
659
 
 
660
 
 
661
    virtual int init();
 
662
 
 
663
    bool matches(uint32_t type, uint32_t fourcc)
 
664
    {
 
665
        return mType == type && mFourcc == fourcc;
 
666
    }
 
667
 
 
668
    bool equals(const VBoxVHWAGlProgramVHWA & other)
 
669
    {
 
670
        return matches(other.mType, other.mFourcc);
 
671
    }
 
672
 
 
673
private:
 
674
    uint32_t mType;
 
675
    uint32_t mFourcc;
 
676
 
 
677
    GLfloat mDstUpperR, mDstUpperG, mDstUpperB;
 
678
    GLint mUniDstUpperColor;
 
679
 
 
680
    GLfloat mDstLowerR, mDstLowerG, mDstLowerB;
 
681
    GLint mUniDstLowerColor;
 
682
 
 
683
    GLfloat mSrcUpperR, mSrcUpperG, mSrcUpperB;
 
684
    GLint mUniSrcUpperColor;
 
685
 
 
686
    GLfloat mSrcLowerR, mSrcLowerG, mSrcLowerB;
 
687
    GLint mUniSrcLowerColor;
 
688
 
 
689
    GLint mDstTex;
 
690
    GLint mUniDstTex;
 
691
 
 
692
    GLint mSrcTex;
 
693
    GLint mUniSrcTex;
 
694
 
 
695
    GLint mVTex;
 
696
    GLint mUniVTex;
 
697
 
 
698
    GLint mUTex;
 
699
    GLint mUniUTex;
 
700
 
 
701
//    VBoxVHWAGlProgram *mpProgram;
 
702
//
 
703
//    class VBoxVHWAGlProgramMngr *mpMngr;
 
704
};
 
705
 
 
706
VBoxVHWAGlProgramVHWA::VBoxVHWAGlProgramVHWA(/*VBoxVHWAGlProgramMngr *aMngr, */uint32_t type, uint32_t fourcc, VBoxVHWAGlShader ** apShaders, int acShaders) :
 
707
    VBoxVHWAGlProgram(apShaders, acShaders),
 
708
    mType(type),
 
709
    mFourcc(fourcc),
 
710
    mDstUpperR(0.0), mDstUpperG(0.0), mDstUpperB(0.0),
 
711
    mUniDstUpperColor(-1),
 
712
    mDstLowerR(0.0), mDstLowerG(0.0), mDstLowerB(0.0),
 
713
    mUniDstLowerColor(-1),
 
714
    mSrcUpperR(0.0), mSrcUpperG(0.0), mSrcUpperB(0.0),
 
715
    mUniSrcUpperColor(-1),
 
716
    mSrcLowerR(0.0), mSrcLowerG(0.0), mSrcLowerB(0.0),
 
717
    mUniSrcLowerColor(-1),
 
718
//    mpMngr(aMngr),
 
719
    mDstTex(-1),
 
720
    mUniDstTex(-1),
 
721
    mSrcTex(-1),
 
722
    mUniSrcTex(-1),
 
723
    mVTex(-1),
 
724
    mUniVTex(-1),
 
725
    mUTex(-1),
 
726
    mUniUTex(-1)
 
727
{}
 
728
 
 
729
int VBoxVHWAGlProgramVHWA::init()
 
730
{
 
731
    int rc = VBoxVHWAGlProgram::init();
 
732
    if(RT_FAILURE(rc))
 
733
        return rc;
 
734
    if(rc == VINF_ALREADY_INITIALIZED)
 
735
        return rc;
 
736
 
 
737
    start();
 
738
 
 
739
    rc = VERR_GENERAL_FAILURE;
 
740
 
 
741
    do
 
742
    {
 
743
        GLint tex = 0;
 
744
        mUniSrcTex = vboxglGetUniformLocation(program(), "uSrcTex");
 
745
        Assert(mUniSrcTex != -1);
 
746
        if(mUniSrcTex == -1)
 
747
            break;
 
748
 
 
749
        VBOXQGL_CHECKERR(
 
750
                vboxglUniform1i(mUniSrcTex, tex);
 
751
                );
 
752
        mSrcTex = tex;
 
753
        ++tex;
 
754
 
 
755
        if(type() & VBOXVHWA_PROGRAM_SRCCOLORKEY)
 
756
        {
 
757
            mUniSrcLowerColor = vboxglGetUniformLocation(program(), "uSrcClr");
 
758
            Assert(mUniSrcLowerColor != -1);
 
759
            if(mUniSrcLowerColor == -1)
 
760
                break;
 
761
 
 
762
            mSrcLowerR = 0.0; mSrcLowerG = 0.0; mSrcLowerB = 0.0;
 
763
 
 
764
            VBOXQGL_CHECKERR(
 
765
                    vboxglUniform4f(mUniSrcLowerColor, 0.0, 0.0, 0.0, 0.0);
 
766
                    );
 
767
        }
 
768
 
 
769
        if(type() & VBOXVHWA_PROGRAM_COLORCONV)
 
770
        {
 
771
            switch(fourcc())
 
772
            {
 
773
                case FOURCC_YV12:
 
774
                {
 
775
                    mUniVTex = vboxglGetUniformLocation(program(), "uVTex");
 
776
                    Assert(mUniVTex != -1);
 
777
                    if(mUniVTex == -1)
 
778
                        break;
 
779
 
 
780
                    VBOXQGL_CHECKERR(
 
781
                            vboxglUniform1i(mUniVTex, tex);
 
782
                            );
 
783
                    mVTex = tex;
 
784
                    ++tex;
 
785
 
 
786
                    mUniUTex = vboxglGetUniformLocation(program(), "uUTex");
 
787
                    Assert(mUniUTex != -1);
 
788
                    if(mUniUTex == -1)
 
789
                        break;
 
790
                    VBOXQGL_CHECKERR(
 
791
                            vboxglUniform1i(mUniUTex, tex);
 
792
                            );
 
793
                    mUTex = tex;
 
794
                    ++tex;
 
795
 
 
796
                    break;
 
797
                }
 
798
                case FOURCC_UYVY:
 
799
                case FOURCC_YUY2:
 
800
                case FOURCC_AYUV:
 
801
                    break;
 
802
                default:
 
803
                    Assert(0);
 
804
                    break;
 
805
            }
 
806
        }
 
807
 
 
808
        if(type() & VBOXVHWA_PROGRAM_DSTCOLORKEY)
 
809
        {
 
810
 
 
811
            mUniDstTex = vboxglGetUniformLocation(program(), "uDstTex");
 
812
            Assert(mUniDstTex != -1);
 
813
            if(mUniDstTex == -1)
 
814
                break;
 
815
            VBOXQGL_CHECKERR(
 
816
                    vboxglUniform1i(mUniDstTex, tex);
 
817
                    );
 
818
            mDstTex = tex;
 
819
            ++tex;
 
820
 
 
821
            mUniDstLowerColor = vboxglGetUniformLocation(program(), "uDstClr");
 
822
            Assert(mUniDstLowerColor != -1);
 
823
            if(mUniDstLowerColor == -1)
 
824
                break;
 
825
 
 
826
            mDstLowerR = 0.0; mDstLowerG = 0.0; mDstLowerB = 0.0;
 
827
 
 
828
            VBOXQGL_CHECKERR(
 
829
                    vboxglUniform4f(mUniDstLowerColor, 0.0, 0.0, 0.0, 0.0);
 
830
                    );
 
831
        }
 
832
 
 
833
        rc = VINF_SUCCESS;
 
834
    } while(0);
 
835
 
 
836
 
 
837
    stop();
 
838
    if(rc == VINF_SUCCESS)
 
839
        return VINF_SUCCESS;
 
840
 
 
841
    Assert(0);
 
842
    VBoxVHWAGlProgram::uninit();
 
843
    return VERR_GENERAL_FAILURE;
 
844
}
 
845
 
 
846
int VBoxVHWAGlProgramVHWA::setDstCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b)
 
847
{
 
848
    Assert(isInitialized());
 
849
    if(!isInitialized())
 
850
        return VERR_GENERAL_FAILURE;
 
851
    if(mDstUpperR == r && mDstUpperG == g && mDstUpperB == b)
 
852
        return VINF_ALREADY_INITIALIZED;
 
853
    vboxglUniform4f(mUniDstUpperColor, r, g, b, 0.0);
 
854
    mDstUpperR = r;
 
855
    mDstUpperG = g;
 
856
    mDstUpperB = b;
 
857
    return VINF_SUCCESS;
 
858
}
 
859
 
 
860
int VBoxVHWAGlProgramVHWA::setDstCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b)
 
861
{
 
862
    Assert(isInitialized());
 
863
    if(!isInitialized())
 
864
        return VERR_GENERAL_FAILURE;
 
865
    if(mDstLowerR == r && mDstLowerG == g && mDstLowerB == b)
 
866
        return VINF_ALREADY_INITIALIZED;
 
867
 
 
868
//    VBOXQGLLOG(("setDstCKeyLowerRange: r(%f), g(%f), b(%f)\n", r, g, b));
 
869
    VBOXQGL_CHECKERR(
 
870
            vboxglUniform4f(mUniDstLowerColor, r, g, b, 0.0);
 
871
            );
 
872
 
 
873
    mDstLowerR = r;
 
874
    mDstLowerG = g;
 
875
    mDstLowerB = b;
 
876
    return VINF_SUCCESS;
 
877
}
 
878
 
 
879
int VBoxVHWAGlProgramVHWA::setSrcCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b)
 
880
{
 
881
    Assert(isInitialized());
 
882
    if(!isInitialized())
 
883
        return VERR_GENERAL_FAILURE;
 
884
    if(mSrcUpperR == r && mSrcUpperG == g && mSrcUpperB == b)
 
885
        return VINF_ALREADY_INITIALIZED;
 
886
    vboxglUniform4f(mUniSrcUpperColor, r, g, b, 0.0);
 
887
    mSrcUpperR = r;
 
888
    mSrcUpperG = g;
 
889
    mSrcUpperB = b;
 
890
    return VINF_SUCCESS;
 
891
}
 
892
 
 
893
int VBoxVHWAGlProgramVHWA::setSrcCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b)
 
894
{
 
895
    Assert(isInitialized());
 
896
    if(!isInitialized())
 
897
        return VERR_GENERAL_FAILURE;
 
898
    if(mSrcLowerR == r && mSrcLowerG == g && mSrcLowerB == b)
 
899
        return VINF_ALREADY_INITIALIZED;
 
900
    VBOXQGL_CHECKERR(
 
901
            vboxglUniform4f(mUniSrcLowerColor, r, g, b, 0.0);
 
902
            );
 
903
    mSrcLowerR = r;
 
904
    mSrcLowerG = g;
 
905
    mSrcLowerB = b;
 
906
    return VINF_SUCCESS;
 
907
}
 
908
 
 
909
class VBoxVHWAGlProgramMngr
 
910
{
 
911
public:
 
912
    VBoxVHWAGlProgramMngr() :
 
913
        mShaderCConvApplyAYUV(":/cconvApplyAYUV.c", GL_FRAGMENT_SHADER),
 
914
        mShaderCConvAYUV(":/cconvAYUV.c", GL_FRAGMENT_SHADER),
 
915
//        mShaderCConvAYUVVoid(":/cconvAYUV_void.c", GL_FRAGMENT_SHADER),
 
916
        mShaderCConvBGR(":/cconvBGR.c", GL_FRAGMENT_SHADER),
 
917
//        mShaderCConvBGRVoid(":/cconvBGR_void.c", GL_FRAGMENT_SHADER),
 
918
        mShaderCConvUYVY(":/cconvUYVY.c", GL_FRAGMENT_SHADER),
 
919
//        mShaderCConvUYVYVoid(":/cconvUYVY_void.c", GL_FRAGMENT_SHADER),
 
920
        mShaderCConvYUY2(":/cconvYUY2.c", GL_FRAGMENT_SHADER),
 
921
//        mShaderCConvYUY2Void(":/cconvYUY2_void.c", GL_FRAGMENT_SHADER),
 
922
        mShaderCConvYV12(":/cconvYV12.c", GL_FRAGMENT_SHADER),
 
923
//        mShaderCConvYV12Void(":/cconvYV12_void.c", GL_FRAGMENT_SHADER),
 
924
        mShaderSplitBGRA(":/splitBGRA.c", GL_FRAGMENT_SHADER),
 
925
        mShaderCKeyDst(":/ckeyDst.c", GL_FRAGMENT_SHADER),
 
926
        mShaderCKeyDst2(":/ckeyDst2.c", GL_FRAGMENT_SHADER),
 
927
//        mShaderCKeyDstVoid(":/ckeyDst_void.c", GL_FRAGMENT_SHADER),
 
928
    //  mShaderCKeySrc;
 
929
    //  mShaderCKeySrcVoid;
 
930
        mShaderMainOverlay(":/mainOverlay.c", GL_FRAGMENT_SHADER),
 
931
        mShaderMainOverlayNoCKey(":/mainOverlayNoCKey.c", GL_FRAGMENT_SHADER),
 
932
        mShaderMainOverlayNoDiscard(":/mainOverlayNoDiscard.c", GL_FRAGMENT_SHADER),
 
933
        mShaderMainOverlayNoDiscard2(":/mainOverlayNoDiscard2.c", GL_FRAGMENT_SHADER)
 
934
    {}
 
935
 
 
936
    VBoxVHWAGlProgramVHWA * getProgram(uint32_t type, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo);
 
937
 
 
938
    void stopCurrentProgram()
 
939
    {
 
940
        VBOXQGL_CHECKERR(
 
941
            vboxglUseProgram(0);
 
942
            );
 
943
    }
 
944
private:
 
945
    VBoxVHWAGlProgramVHWA * searchProgram(uint32_t type, uint32_t fourcc, bool bCreate);
 
946
 
 
947
    VBoxVHWAGlProgramVHWA * createProgram(uint32_t type, uint32_t fourcc);
 
948
 
 
949
//    int startProgram(VBoxVHWAGlProgramVHWA * pProgram) {mCurrentProgram = pProgram; return pProgram->start();}
 
950
 
 
951
    typedef std::list <VBoxVHWAGlProgramVHWA*> ProgramList;
 
952
 
 
953
//    VBoxVHWAGlProgramVHWA * mCurrentProgram;
 
954
    ProgramList mPrograms;
 
955
 
 
956
    VBoxVHWAGlShaderComponent mShaderCConvApplyAYUV;
 
957
 
 
958
    VBoxVHWAGlShaderComponent mShaderCConvAYUV;
 
959
//    VBoxVHWAGlShaderComponent mShaderCConvAYUVVoid;
 
960
    VBoxVHWAGlShaderComponent mShaderCConvBGR;
 
961
//    VBoxVHWAGlShaderComponent mShaderCConvBGRVoid;
 
962
    VBoxVHWAGlShaderComponent mShaderCConvUYVY;
 
963
//    VBoxVHWAGlShaderComponent mShaderCConvUYVYVoid;
 
964
    VBoxVHWAGlShaderComponent mShaderCConvYUY2;
 
965
//    VBoxVHWAGlShaderComponent mShaderCConvYUY2Void;
 
966
    VBoxVHWAGlShaderComponent mShaderCConvYV12;
 
967
//    VBoxVHWAGlShaderComponent mShaderCConvYV12Void;
 
968
    VBoxVHWAGlShaderComponent mShaderSplitBGRA;
 
969
 
 
970
    /* expected the dst surface texture to be bound to the 1-st tex unit */
 
971
    VBoxVHWAGlShaderComponent mShaderCKeyDst;
 
972
    /* expected the dst surface texture to be bound to the 2-nd tex unit */
 
973
    VBoxVHWAGlShaderComponent mShaderCKeyDst2;
 
974
//    VBoxVHWAGlShaderComponent mShaderCKeyDstVoid;
 
975
//    VBoxVHWAGlShaderComponent mShaderCKeySrc;
 
976
//    VBoxVHWAGlShaderComponent mShaderCKeySrcVoid;
 
977
 
 
978
    VBoxVHWAGlShaderComponent mShaderMainOverlay;
 
979
    VBoxVHWAGlShaderComponent mShaderMainOverlayNoCKey;
 
980
    VBoxVHWAGlShaderComponent mShaderMainOverlayNoDiscard;
 
981
    VBoxVHWAGlShaderComponent mShaderMainOverlayNoDiscard2;
 
982
 
 
983
    friend class VBoxVHWAGlProgramVHWA;
 
984
};
 
985
 
 
986
VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::createProgram(uint32_t type, uint32_t fourcc)
 
987
{
 
988
    VBoxVHWAGlShaderComponent * apShaders[16];
 
989
    uint32_t cShaders = 0;
 
990
 
 
991
    /* workaround for NVIDIA driver bug: ensure we attach the shader before those it is used in */
 
992
    /* reserve a slot for the mShaderCConvApplyAYUV,
 
993
     * in case it is not used the slot will be occupied by mShaderCConvBGR , which is ok */
 
994
    cShaders++;
 
995
 
 
996
    if(!!(type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
 
997
            && !(type & VBOXVHWA_PROGRAM_COLORKEYNODISCARD))
 
998
    {
 
999
        if(fourcc == FOURCC_YV12)
 
1000
        {
 
1001
            apShaders[cShaders++] = &mShaderCKeyDst2;
 
1002
        }
 
1003
        else
 
1004
        {
 
1005
            apShaders[cShaders++] = &mShaderCKeyDst;
 
1006
        }
 
1007
    }
 
1008
// ensure we don't have empty functions /* paranoya for for ATI on linux */
 
1009
//    else
 
1010
//    {
 
1011
//        apShaders[cShaders++] = &mShaderCKeyDstVoid;
 
1012
//    }
 
1013
 
 
1014
    if(type & VBOXVHWA_PROGRAM_SRCCOLORKEY)
 
1015
    {
 
1016
        Assert(0);
 
1017
        /* disabled for now, not really necessary for video overlaying */
 
1018
    }
 
1019
 
 
1020
    bool bFound = false;
 
1021
 
 
1022
//    if(type & VBOXVHWA_PROGRAM_COLORCONV)
 
1023
    {
 
1024
        if(fourcc == FOURCC_UYVY)
 
1025
        {
 
1026
            apShaders[cShaders++] = &mShaderCConvUYVY;
 
1027
            bFound = true;
 
1028
        }
 
1029
        else if(fourcc == FOURCC_YUY2)
 
1030
        {
 
1031
            apShaders[cShaders++] = &mShaderCConvYUY2;
 
1032
            bFound = true;
 
1033
        }
 
1034
        else if(fourcc == FOURCC_YV12)
 
1035
        {
 
1036
//            apShaders[cShaders++] = &mShaderSplitBGRA;
 
1037
            apShaders[cShaders++] = &mShaderCConvYV12;
 
1038
            bFound = true;
 
1039
        }
 
1040
        else if(fourcc == FOURCC_AYUV)
 
1041
        {
 
1042
            apShaders[cShaders++] = &mShaderCConvAYUV;
 
1043
            bFound = true;
 
1044
        }
 
1045
    }
 
1046
 
 
1047
    if(bFound)
 
1048
    {
 
1049
        type |= VBOXVHWA_PROGRAM_COLORCONV;
 
1050
        apShaders[0] = &mShaderCConvApplyAYUV;
 
1051
    }
 
1052
    else
 
1053
    {
 
1054
        type &= (~VBOXVHWA_PROGRAM_COLORCONV);
 
1055
        apShaders[0] = &mShaderCConvBGR;
 
1056
    }
 
1057
 
 
1058
    if(type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
 
1059
    {
 
1060
        if(type & VBOXVHWA_PROGRAM_COLORKEYNODISCARD)
 
1061
        {
 
1062
            if(fourcc == FOURCC_YV12)
 
1063
            {
 
1064
                apShaders[cShaders++] = &mShaderMainOverlayNoDiscard2;
 
1065
            }
 
1066
            else
 
1067
            {
 
1068
                apShaders[cShaders++] = &mShaderMainOverlayNoDiscard;
 
1069
            }
 
1070
        }
 
1071
        else
 
1072
        {
 
1073
            apShaders[cShaders++] = &mShaderMainOverlay;
 
1074
        }
 
1075
    }
 
1076
    else
 
1077
    {
 
1078
        // ensure we don't have empty functions /* paranoya for for ATI on linux */
 
1079
        apShaders[cShaders++] = &mShaderMainOverlayNoCKey;
 
1080
    }
 
1081
 
 
1082
    Assert(cShaders <= RT_ELEMENTS(apShaders));
 
1083
 
 
1084
    VBoxVHWAGlShader shader(GL_FRAGMENT_SHADER, apShaders, cShaders);
 
1085
    VBoxVHWAGlShader *pShader = &shader;
 
1086
 
 
1087
    VBoxVHWAGlProgramVHWA *pProgram =  new VBoxVHWAGlProgramVHWA(/*this, */type, fourcc, &pShader, 1);
 
1088
    pProgram->init();
 
1089
 
 
1090
    return pProgram;
 
1091
}
 
1092
 
 
1093
VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::getProgram(uint32_t type, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo)
 
1094
{
 
1095
    Q_UNUSED(pTo);
 
1096
    uint32_t fourcc = 0;
 
1097
    type &= VBOXVHWA_SUPPORTED_PROGRAM;
 
1098
 
 
1099
    if(pFrom && pFrom->fourcc())
 
1100
    {
 
1101
        fourcc = pFrom->fourcc();
 
1102
        type |= VBOXVHWA_PROGRAM_COLORCONV;
 
1103
    }
 
1104
    else
 
1105
    {
 
1106
        type &= (~VBOXVHWA_PROGRAM_COLORCONV);
 
1107
    }
 
1108
 
 
1109
    if(!(type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
 
1110
            && !(type & VBOXVHWA_PROGRAM_SRCCOLORKEY))
 
1111
    {
 
1112
        type &= (~VBOXVHWA_PROGRAM_COLORKEYNODISCARD);
 
1113
    }
 
1114
 
 
1115
    if(type)
 
1116
        return searchProgram(type, fourcc, true);
 
1117
    return NULL;
 
1118
}
 
1119
 
 
1120
VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::searchProgram(uint32_t type, uint32_t fourcc, bool bCreate)
 
1121
{
 
1122
//    if(mCurrentProgram && mCurrentProgram->matches(type))
 
1123
//        return mCurrentProgram;
 
1124
 
 
1125
    for (ProgramList::const_iterator it = mPrograms.begin();
 
1126
         it != mPrograms.end(); ++ it)
 
1127
    {
 
1128
        if (!(*it)->matches(type, fourcc))
 
1129
        {
 
1130
            continue;
 
1131
        }
 
1132
        return *it;
 
1133
    }
 
1134
    if(bCreate)
 
1135
    {
 
1136
        VBoxVHWAGlProgramVHWA *pProgram = createProgram(type, fourcc);
 
1137
        if(pProgram)
 
1138
        {
 
1139
            mPrograms.push_back(pProgram);
 
1140
            return pProgram;
 
1141
        }
 
1142
    }
 
1143
    return NULL;
 
1144
}
 
1145
 
 
1146
int VBoxVHWASurfaceBase::setCKey(VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey, bool bDst)
 
1147
{
 
1148
    float r,g,b;
 
1149
//    pProgram->start();
 
1150
//    pFormat->pixel2Normalized(pCKey->upper(), &r, &g, &b);
 
1151
//    int rcU = pProgram->setCKeyUpperRange(r, g, b);
 
1152
//    Assert(RT_SUCCESS(rcU));
 
1153
    pFormat->pixel2Normalized(pCKey->lower(), &r, &g, &b);
 
1154
    int rcL = bDst ? pProgram->setDstCKeyLowerRange(r, g, b) : pProgram->setSrcCKeyLowerRange(r, g, b);
 
1155
    Assert(RT_SUCCESS(rcL));
 
1156
//    pProgram->stop();
 
1157
 
 
1158
    return RT_SUCCESS(rcL) /*&& RT_SUCCESS(rcU)*/ ? VINF_SUCCESS: VERR_GENERAL_FAILURE;
 
1159
}
 
1160
 
 
1161
 
 
1162
 
 
1163
void VBoxVHWASurfaceBase::setAddress(uchar * addr)
 
1164
{
 
1165
    Assert(addr);
 
1166
    if(!addr) return;
 
1167
    if(addr == mAddress) return;
 
1168
 
 
1169
    if(mFreeAddress)
 
1170
    {
 
1171
        free(mAddress);
 
1172
    }
 
1173
 
 
1174
    mAddress = addr;
 
1175
    mFreeAddress = false;
 
1176
 
 
1177
#ifdef VBOXVHWA_USE_TEXGROUP
 
1178
    for(int i = mpTex.numSets()-1; i >=0; --i)
 
1179
    {
 
1180
#endif
 
1181
    mpTex[0]->setAddress(mAddress);
 
1182
    if(fourcc() == FOURCC_YV12)
 
1183
    {
 
1184
        uchar *pTexAddr = mAddress+mpTex[0]->memSize();
 
1185
        mpTex[1]->setAddress(pTexAddr);
 
1186
        pTexAddr = pTexAddr+mpTex[1]->memSize();
 
1187
        mpTex[2]->setAddress(pTexAddr);
 
1188
    }
 
1189
#ifdef VBOXVHWA_USE_TEXGROUP
 
1190
    mpTex.swap();
 
1191
    }
 
1192
#endif
 
1193
 
 
1194
//    makeCurrent();
 
1195
//    updateTexture(&mRect);
 
1196
    mUpdateMem2TexRect.set(mRect);
 
1197
    Assert(!mUpdateMem2TexRect.isClear());
 
1198
    Assert(mRect.contains(mUpdateMem2TexRect.rect()));
 
1199
//    mUpdateTex2FBRect.clear();
 
1200
//    Assert(mUpdateTex2FBRect.isClear());
 
1201
}
 
1202
 
 
1203
void VBoxVHWASurfaceBase::globalInit()
 
1204
{
 
1205
    VBOXQGLLOG(("globalInit\n"));
 
1206
 
 
1207
//    glEnable(GL_TEXTURE_2D);
 
1208
    glEnable(GL_TEXTURE_RECTANGLE);
 
1209
    glDisable(GL_DEPTH_TEST);
 
1210
 
 
1211
    VBOXQGL_CHECKERR(
 
1212
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
1213
            );
 
1214
    VBOXQGL_CHECKERR(
 
1215
            glPixelStorei(GL_PACK_ALIGNMENT, 1);
 
1216
            );
 
1217
//
 
1218
//    VBOXQGL_CHECKERR(
 
1219
//            vboxglActiveTexture(GL_TEXTURE1);
 
1220
//        );
 
1221
//    VBOXQGL_CHECKERR(
 
1222
//            glEnable(GL_TEXTURE_2D);
 
1223
//            );
 
1224
//    VBOXQGL_CHECKERR(
 
1225
//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
1226
//            );
 
1227
//    VBOXQGL_CHECKERR(
 
1228
//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
1229
//            );
 
1230
//    VBOXQGL_CHECKERR(
 
1231
//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 
1232
//            );
 
1233
//    VBOXQGL_CHECKERR(
 
1234
//            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 
1235
//            );
 
1236
//
 
1237
//    VBOXQGL_CHECKERR(
 
1238
//            vboxglActiveTexture(GL_TEXTURE0);
 
1239
//        );
 
1240
//    VBOXQGL_CHECKERR(
 
1241
//            glEnable(GL_TEXTURE_2D);
 
1242
//            );
 
1243
//    VBOXQGL_CHECKERR(
 
1244
//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
1245
//            );
 
1246
//    VBOXQGL_CHECKERR(
 
1247
//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
1248
//            );
 
1249
//    VBOXQGL_CHECKERR(
 
1250
//            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 
1251
//            );
 
1252
//    VBOXQGL_CHECKERR(
 
1253
//            glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 
1254
//            );
 
1255
}
 
1256
 
 
1257
VBoxVHWASurfaceBase::VBoxVHWASurfaceBase(class VBoxGLWidget *aWidget,
 
1258
        const QSize & aSize,
 
1259
        const QRect & aTargRect,
 
1260
        const QRect & aSrcRect,
 
1261
        const QRect & aVisTargRect,
 
1262
        VBoxVHWAColorFormat & aColorFormat,
 
1263
        VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
 
1264
                    VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey,
 
1265
#ifdef VBOXVHWA_USE_TEXGROUP
 
1266
                    uint32_t cBackTex,
 
1267
#endif
 
1268
                    bool bVGA) :
 
1269
                mRect(0,0,aSize.width(),aSize.height()),
 
1270
                mpProgram(NULL),
 
1271
                mVisibleDisplayInitialized(false),
 
1272
                mNeedVisibilityReinit(true),
 
1273
                mNotIntersected(false),
 
1274
                mAddress(NULL),
 
1275
                mColorFormat(aColorFormat),
 
1276
                mpSrcBltCKey(NULL),
 
1277
                mpDstBltCKey(NULL),
 
1278
                mpSrcOverlayCKey(NULL),
 
1279
                mpDstOverlayCKey(NULL),
 
1280
                mpDefaultDstOverlayCKey(NULL),
 
1281
                mpDefaultSrcOverlayCKey(NULL),
 
1282
                mLockCount(0),
 
1283
                mFreeAddress(false),
 
1284
                mComplexList(NULL),
 
1285
                mWidget(aWidget),
 
1286
                mHGHandle(VBOXVHWA_SURFHANDLE_INVALID)
 
1287
#ifdef DEBUG
 
1288
                ,
 
1289
                cFlipsCurr(0),
 
1290
                cFlipsTarg(0)
 
1291
#endif
 
1292
{
 
1293
    setDstBltCKey(pDstBltCKey);
 
1294
    setSrcBltCKey(pSrcBltCKey);
 
1295
 
 
1296
    setDefaultDstOverlayCKey(pDstOverlayCKey);
 
1297
    resetDefaultDstOverlayCKey();
 
1298
 
 
1299
    setDefaultSrcOverlayCKey(pSrcOverlayCKey);
 
1300
    resetDefaultSrcOverlayCKey();
 
1301
 
 
1302
#ifdef VBOXVHWA_USE_TEXGROUP
 
1303
    mpTex.init(mColorFormat.fourcc() == FOURCC_YV12 ? 3 : 1, cBackTex);
 
1304
    Assert(mpTex.numSets());
 
1305
    for(int i = mpTex.numSets()-1; i >=0; --i)
 
1306
    {
 
1307
#endif
 
1308
    mpTex[0] = vboxVHWATextureCreate(mWidget->context(), QRect(0,0,aSize.width(),aSize.height()), mColorFormat, bVGA);
 
1309
    if(mColorFormat.fourcc() == FOURCC_YV12)
 
1310
    {
 
1311
        QRect rect(0,0,aSize.width()/2,aSize.height()/2);
 
1312
        mpTex[1] = vboxVHWATextureCreate(mWidget->context(), rect, mColorFormat, bVGA);
 
1313
        mpTex[2] = vboxVHWATextureCreate(mWidget->context(), rect, mColorFormat, bVGA);
 
1314
    }
 
1315
#ifdef VBOXVHWA_USE_TEXGROUP
 
1316
    mpTex.swap();
 
1317
    }
 
1318
#endif
 
1319
 
 
1320
    setRectValues(aTargRect, aSrcRect);
 
1321
    setVisibleRectValues(aVisTargRect);
 
1322
//    mTargSize = QRect(0, 0, aTargSize->width(), aTargSize->height());
 
1323
 
 
1324
//    mBytesPerPixel = calcBytesPerPixel(mColorFormat.format(), mColorFormat.type());
 
1325
//    mBytesPerLine = mRect.width() * mBytesPerPixel;
 
1326
}
 
1327
 
 
1328
VBoxVHWASurfaceBase::~VBoxVHWASurfaceBase()
 
1329
{
 
1330
    uninit();
 
1331
}
 
1332
 
 
1333
GLsizei VBoxVHWASurfaceBase::makePowerOf2(GLsizei val)
 
1334
{
 
1335
    int last = ASMBitLastSetS32(val);
 
1336
    if(last>1)
 
1337
    {
 
1338
        last--;
 
1339
        if((1 << last) != val)
 
1340
        {
 
1341
            Assert((1 << last) < val);
 
1342
            val = (1 << (last+1));
 
1343
        }
 
1344
    }
 
1345
    return val;
 
1346
}
 
1347
 
 
1348
ulong VBoxVHWASurfaceBase::calcBytesPerPixel(GLenum format, GLenum type)
 
1349
{
 
1350
    /* we now support only common byte-aligned data */
 
1351
    int numComponents = 0;
 
1352
    switch(format)
 
1353
    {
 
1354
    case GL_COLOR_INDEX:
 
1355
    case GL_RED:
 
1356
    case GL_GREEN:
 
1357
    case GL_BLUE:
 
1358
    case GL_ALPHA:
 
1359
    case GL_LUMINANCE:
 
1360
        numComponents = 1;
 
1361
        break;
 
1362
    case GL_RGB:
 
1363
    case GL_BGR_EXT:
 
1364
        numComponents = 3;
 
1365
        break;
 
1366
    case GL_RGBA:
 
1367
    case GL_BGRA_EXT:
 
1368
        numComponents = 4;
 
1369
        break;
 
1370
    case GL_LUMINANCE_ALPHA:
 
1371
        numComponents = 2;
 
1372
        break;
 
1373
    default:
 
1374
        Assert(0);
 
1375
        break;
 
1376
    }
 
1377
 
 
1378
    int componentSize = 0;
 
1379
    switch(type)
 
1380
    {
 
1381
    case GL_UNSIGNED_BYTE:
 
1382
    case GL_BYTE:
 
1383
        componentSize = 1;
 
1384
        break;
 
1385
    //case GL_BITMAP:
 
1386
    case  GL_UNSIGNED_SHORT:
 
1387
    case GL_SHORT:
 
1388
        componentSize = 2;
 
1389
        break;
 
1390
    case GL_UNSIGNED_INT:
 
1391
    case GL_INT:
 
1392
    case GL_FLOAT:
 
1393
        componentSize = 4;
 
1394
        break;
 
1395
    default:
 
1396
        Assert(0);
 
1397
        break;
 
1398
    }
 
1399
    return numComponents * componentSize;
 
1400
}
 
1401
 
 
1402
void VBoxVHWASurfaceBase::uninit()
 
1403
{
 
1404
//    mState->makeCurrent(this);
 
1405
 
 
1406
    deleteDisplay();
 
1407
 
 
1408
#ifdef VBOXVHWA_USE_TEXGROUP
 
1409
    for(int i = mpTex.numSets()-1; i >=0; --i)
 
1410
    {
 
1411
#endif
 
1412
    delete mpTex[0];
 
1413
    if(fourcc() == FOURCC_YV12)
 
1414
    {
 
1415
        delete mpTex[1];
 
1416
        delete mpTex[2];
 
1417
    }
 
1418
#ifdef VBOXVHWA_USE_TEXGROUP
 
1419
    mpTex.swap();
 
1420
    }
 
1421
#endif
 
1422
 
 
1423
    if(mAddress && mFreeAddress)
 
1424
    {
 
1425
        free(mAddress);
 
1426
        mAddress = NULL;
 
1427
    }
 
1428
}
 
1429
 
 
1430
ulong VBoxVHWASurfaceBase::memSize()
 
1431
{
 
1432
    ulong size = mpTex[0]->memSize();
 
1433
    if(fourcc() == FOURCC_YV12)
 
1434
    {
 
1435
        size += mpTex[1]->memSize() + mpTex[2]->memSize();
 
1436
    }
 
1437
    return size;
 
1438
}
 
1439
 
 
1440
void VBoxVHWASurfaceBase::init(VBoxVHWASurfaceBase * pPrimary, uchar *pvMem)
 
1441
{
 
1442
    if(pPrimary)
 
1443
    {
 
1444
        VBOXQGL_CHECKERR(
 
1445
                vboxglActiveTexture(GL_TEXTURE1);
 
1446
            );
 
1447
    }
 
1448
 
 
1449
    int size = memSize();
 
1450
    uchar * address = (uchar *)malloc(size);
 
1451
#ifdef DEBUG_misha
 
1452
    int tex0Size = mpTex[0]->memSize();
 
1453
    if(pPrimary)
 
1454
    {
 
1455
        memset(address, 0xff, tex0Size);
 
1456
        Assert(size >= tex0Size);
 
1457
        if(size > tex0Size)
 
1458
        {
 
1459
            memset(address + tex0Size, 0x0, size - tex0Size);
 
1460
        }
 
1461
    }
 
1462
    else
 
1463
    {
 
1464
        memset(address, 0x0f, tex0Size);
 
1465
        Assert(size >= tex0Size);
 
1466
        if(size > tex0Size)
 
1467
        {
 
1468
            memset(address + tex0Size, 0x3f, size - tex0Size);
 
1469
        }
 
1470
    }
 
1471
#else
 
1472
    memset(address, 0, size);
 
1473
#endif
 
1474
 
 
1475
#ifdef VBOXVHWA_USE_TEXGROUP
 
1476
    for(int i = mpTex.numSets()-1; i >=0; --i)
 
1477
    {
 
1478
#endif
 
1479
    mpTex[0]->init(address);
 
1480
    if(fourcc() == FOURCC_YV12)
 
1481
    {
 
1482
        mpTex[1]->init(address);
 
1483
        mpTex[2]->init(address);
 
1484
    }
 
1485
#ifdef VBOXVHWA_USE_TEXGROUP
 
1486
    mpTex.swap();
 
1487
    }
 
1488
#endif
 
1489
 
 
1490
    if(pvMem)
 
1491
    {
 
1492
        mAddress = pvMem;
 
1493
        free(address);
 
1494
        mFreeAddress = false;
 
1495
 
 
1496
    }
 
1497
    else
 
1498
    {
 
1499
        mAddress = address;
 
1500
        mFreeAddress = true;
 
1501
    }
 
1502
 
 
1503
#ifdef VBOXVHWA_USE_TEXGROUP
 
1504
    for(int i = mpTex.numSets()-1; i >=0; --i)
 
1505
    {
 
1506
#endif
 
1507
    mpTex[0]->setAddress(mAddress);
 
1508
    if(fourcc() == FOURCC_YV12)
 
1509
    {
 
1510
        uchar *pTexAddr = mAddress+mpTex[0]->memSize();
 
1511
        mpTex[1]->setAddress(pTexAddr);
 
1512
        pTexAddr = pTexAddr+mpTex[1]->memSize();
 
1513
        mpTex[2]->setAddress(pTexAddr);
 
1514
    }
 
1515
#ifdef VBOXVHWA_USE_TEXGROUP
 
1516
    mpTex.swap();
 
1517
    }
 
1518
#endif
 
1519
 
 
1520
    initDisplay(pPrimary);
 
1521
 
 
1522
    mUpdateMem2TexRect.set(mRect);
 
1523
    Assert(!mUpdateMem2TexRect.isClear());
 
1524
    Assert(mRect.contains(mUpdateMem2TexRect.rect()));
 
1525
 
 
1526
    if(pPrimary)
 
1527
    {
 
1528
        VBOXQGLLOG(("restoring to tex 0"));
 
1529
        VBOXQGL_CHECKERR(
 
1530
                vboxglActiveTexture(GL_TEXTURE0);
 
1531
            );
 
1532
    }
 
1533
 
 
1534
}
 
1535
 
 
1536
#ifdef DEBUGVHWASTRICT
 
1537
bool g_DbgTest = false;
 
1538
#endif
 
1539
 
 
1540
void VBoxVHWATexture::doUpdate(uchar * pAddress, const QRect * pRect)
 
1541
{
 
1542
#ifdef DEBUGVHWASTRICT
 
1543
    if(g_DbgTest)
 
1544
    {
 
1545
        pAddress = (uchar*)malloc(memSize());
 
1546
        uchar val = 0;
 
1547
        for(uint32_t i = 0; i < memSize(); i++)
 
1548
        {
 
1549
            pAddress[i] = val;
 
1550
            val+=64;
 
1551
        }
 
1552
    }
 
1553
#endif
 
1554
 
 
1555
    GLenum tt = texTarget();
 
1556
    if(pRect)
 
1557
    {
 
1558
        Assert(mRect.contains(*pRect));
 
1559
    }
 
1560
    else
 
1561
    {
 
1562
        pRect = &mRect;
 
1563
    }
 
1564
 
 
1565
    Assert(glIsTexture(mTexture));
 
1566
    VBOXQGL_CHECKERR(
 
1567
            glBindTexture(tt, mTexture);
 
1568
            );
 
1569
 
 
1570
    int x = pRect->x()/mColorFormat.widthCompression();
 
1571
    int y = pRect->y()/mColorFormat.heightCompression();
 
1572
    int width = pRect->width()/mColorFormat.widthCompression();
 
1573
    int height = pRect->height()/mColorFormat.heightCompression();
 
1574
 
 
1575
    uchar * address = pAddress + pointOffsetTex(x, y);
 
1576
 
 
1577
    VBOXQGL_CHECKERR(
 
1578
            glPixelStorei(GL_UNPACK_ROW_LENGTH, mRect.width()/mColorFormat.widthCompression());
 
1579
            );
 
1580
 
 
1581
    VBOXQGL_CHECKERR(
 
1582
            glTexSubImage2D(tt,
 
1583
                0,
 
1584
                x, y, width, height,
 
1585
                mColorFormat.format(),
 
1586
                mColorFormat.type(),
 
1587
                address);
 
1588
            );
 
1589
 
 
1590
#ifdef DEBUGVHWASTRICT
 
1591
    if(g_DbgTest)
 
1592
    {
 
1593
        free(pAddress);
 
1594
    }
 
1595
#endif
 
1596
}
 
1597
 
 
1598
void VBoxVHWATexture::texCoord(int x, int y)
 
1599
{
 
1600
    glTexCoord2f(((float)x)/mTexRect.width()/mColorFormat.widthCompression(), ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
 
1601
}
 
1602
 
 
1603
void VBoxVHWATexture::multiTexCoord(GLenum texUnit, int x, int y)
 
1604
{
 
1605
    vboxglMultiTexCoord2f(texUnit, ((float)x)/mTexRect.width()/mColorFormat.widthCompression(), ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
 
1606
}
 
1607
 
 
1608
void VBoxVHWATexture::uninit()
 
1609
{
 
1610
    if(mTexture)
 
1611
    {
 
1612
        glDeleteTextures(1,&mTexture);
 
1613
    }
 
1614
}
 
1615
 
 
1616
VBoxVHWATexture::VBoxVHWATexture(const QRect & aRect, const VBoxVHWAColorFormat &aFormat)
 
1617
        : mAddress(0),
 
1618
          mTexture(0)
 
1619
{
 
1620
    mColorFormat = aFormat;
 
1621
    mRect = aRect;
 
1622
    mBytesPerPixel = mColorFormat.bitsPerPixel()/8;
 
1623
    mBytesPerPixelTex = mColorFormat.bitsPerPixelTex()/8;
 
1624
    mBytesPerLine = mBytesPerPixel * mRect.width();
 
1625
    GLsizei wdt = VBoxVHWASurfaceBase::makePowerOf2(mRect.width()/mColorFormat.widthCompression());
 
1626
    GLsizei hgt = VBoxVHWASurfaceBase::makePowerOf2(mRect.height()/mColorFormat.heightCompression());
 
1627
    mTexRect = QRect(0,0,wdt,hgt);
 
1628
}
 
1629
 
 
1630
void VBoxVHWATexture::initParams()
 
1631
{
 
1632
    GLenum tt = texTarget();
 
1633
 
 
1634
    glTexParameteri(tt, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
1635
    VBOXQGL_ASSERTNOERR();
 
1636
    glTexParameteri(tt, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
1637
    VBOXQGL_ASSERTNOERR();
 
1638
    glTexParameteri(tt, GL_TEXTURE_WRAP_S, GL_CLAMP);
 
1639
    VBOXQGL_ASSERTNOERR();
 
1640
 
 
1641
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
1642
    VBOXQGL_ASSERTNOERR();
 
1643
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
 
1644
    VBOXQGL_ASSERTNOERR();
 
1645
 
 
1646
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
 
1647
    VBOXQGL_ASSERTNOERR();
 
1648
}
 
1649
 
 
1650
void VBoxVHWATexture::load()
 
1651
{
 
1652
    VBOXQGL_CHECKERR(
 
1653
            glPixelStorei(GL_UNPACK_ROW_LENGTH, mTexRect.width());
 
1654
            );
 
1655
 
 
1656
    VBOXQGL_CHECKERR(
 
1657
        glTexImage2D(texTarget(),
 
1658
                0,
 
1659
                  mColorFormat.internalFormat(),
 
1660
                  mTexRect.width(),
 
1661
                  mTexRect.height(),
 
1662
                  0,
 
1663
                  mColorFormat.format(),
 
1664
                  mColorFormat.type(),
 
1665
                  (GLvoid *)mAddress);
 
1666
        );
 
1667
}
 
1668
 
 
1669
void VBoxVHWATexture::init(uchar *pvMem)
 
1670
{
 
1671
//    GLsizei wdt = mTexRect.width();
 
1672
//    GLsizei hgt = mTexRect.height();
 
1673
 
 
1674
    VBOXQGL_CHECKERR(
 
1675
            glGenTextures(1, &mTexture);
 
1676
        );
 
1677
 
 
1678
    VBOXQGLLOG(("tex: %d", mTexture));
 
1679
 
 
1680
    bind();
 
1681
 
 
1682
    initParams();
 
1683
 
 
1684
    setAddress(pvMem);
 
1685
 
 
1686
    load();
 
1687
}
 
1688
 
 
1689
VBoxVHWATexture::~VBoxVHWATexture()
 
1690
{
 
1691
    uninit();
 
1692
}
 
1693
 
 
1694
void VBoxVHWATextureNP2Rect::texCoord(int x, int y)
 
1695
{
 
1696
    glTexCoord2i(x/mColorFormat.widthCompression(), y/mColorFormat.heightCompression());
 
1697
}
 
1698
 
 
1699
void VBoxVHWATextureNP2Rect::multiTexCoord(GLenum texUnit, int x, int y)
 
1700
{
 
1701
    vboxglMultiTexCoord2i(texUnit, x/mColorFormat.widthCompression(), y/mColorFormat.heightCompression());
 
1702
}
 
1703
 
 
1704
GLenum VBoxVHWATextureNP2Rect::texTarget() {return GL_TEXTURE_RECTANGLE; }
 
1705
 
 
1706
bool VBoxVHWASurfaceBase::synchTexMem(const QRect * pRect)
 
1707
{
 
1708
    if(pRect)
 
1709
    {
 
1710
        Assert(mRect.contains(*pRect));
 
1711
    }
 
1712
 
 
1713
    if(mUpdateMem2TexRect.isClear())
 
1714
        return false;
 
1715
 
 
1716
    if(pRect && !mUpdateMem2TexRect.rect().intersects(*pRect))
 
1717
        return false;
 
1718
 
 
1719
#ifdef VBOXVHWA_USE_TEXGROUP
 
1720
    mpTex.swap();
 
1721
#endif
 
1722
 
 
1723
#ifdef VBOXVHWA_PROFILE_FPS
 
1724
    mWidget->reportNewFrame();
 
1725
#endif
 
1726
 
 
1727
    mpTex[0]->update(&mUpdateMem2TexRect.rect());
 
1728
    if(fourcc() == FOURCC_YV12)
 
1729
    {
 
1730
        QRect rect(mUpdateMem2TexRect.rect().x()/2, mUpdateMem2TexRect.rect().y()/2,
 
1731
                mUpdateMem2TexRect.rect().width()/2, mUpdateMem2TexRect.rect().height()/2);
 
1732
        mpTex[1]->update(&rect);
 
1733
        mpTex[2]->update(&rect);
 
1734
    }
 
1735
 
 
1736
#if 0
 
1737
    mUpdateTex2FBRect.add(mUpdateMem2TexRect);
 
1738
    Assert(!mUpdateTex2FBRect.isClear());
 
1739
    Assert(mRect.contains(mUpdateTex2FBRect.rect()));
 
1740
#endif
 
1741
    mUpdateMem2TexRect.clear();
 
1742
    Assert(mUpdateMem2TexRect.isClear());
 
1743
//#ifdef DEBUG
 
1744
//    VBOXPRINTDIF(dbgTime, ("texMem:"));
 
1745
//#endif
 
1746
    return true;
 
1747
}
 
1748
 
 
1749
void VBoxVHWATextureNP2RectPBO::init(uchar *pvMem)
 
1750
{
 
1751
    VBOXQGL_CHECKERR(
 
1752
            vboxglGenBuffers(1, &mPBO);
 
1753
            );
 
1754
    VBoxVHWATextureNP2Rect::init(pvMem);
 
1755
}
 
1756
 
 
1757
void VBoxVHWATextureNP2RectPBO::doUpdate(uchar * pAddress, const QRect * pRect)
 
1758
{
 
1759
    Q_UNUSED(pAddress);
 
1760
    Q_UNUSED(pRect);
 
1761
 
 
1762
    vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
 
1763
 
 
1764
    GLvoid *buf;
 
1765
 
 
1766
    VBOXQGL_CHECKERR(
 
1767
            buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
 
1768
            );
 
1769
    Assert(buf);
 
1770
    if(buf)
 
1771
    {
 
1772
//    updateBuffer((uchar*)buf, pRect);
 
1773
        memcpy(buf, mAddress, memSize());
 
1774
 
 
1775
        bool unmapped;
 
1776
        VBOXQGL_CHECKERR(
 
1777
                unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
 
1778
                );
 
1779
 
 
1780
        Assert(unmapped);
 
1781
 
 
1782
        VBoxVHWATextureNP2Rect::doUpdate(0, &mRect);
 
1783
 
 
1784
        vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
1785
    }
 
1786
    else
 
1787
    {
 
1788
        VBOXQGLLOGREL(("failed to map PBO, trying fallback to non-PBO approach\n"));
 
1789
        /* try fallback to non-PBO approach */
 
1790
        vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
1791
        VBoxVHWATextureNP2Rect::doUpdate(pAddress, pRect);
 
1792
    }
 
1793
}
 
1794
 
 
1795
VBoxVHWATextureNP2RectPBO::~VBoxVHWATextureNP2RectPBO()
 
1796
{
 
1797
    VBOXQGL_CHECKERR(
 
1798
            vboxglDeleteBuffers(1, &mPBO);
 
1799
            );
 
1800
}
 
1801
 
 
1802
 
 
1803
void VBoxVHWATextureNP2RectPBO::load()
 
1804
{
 
1805
    VBoxVHWATextureNP2Rect::load();
 
1806
 
 
1807
    VBOXQGL_CHECKERR(
 
1808
            vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
 
1809
        );
 
1810
 
 
1811
    VBOXQGL_CHECKERR(
 
1812
            vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, memSize(), NULL, GL_STREAM_DRAW);
 
1813
        );
 
1814
 
 
1815
    GLvoid *buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
 
1816
    Assert(buf);
 
1817
    if(buf)
 
1818
    {
 
1819
    //  updateBuffer((uchar*)buf, &mRect);
 
1820
        memcpy(buf, mAddress, memSize());
 
1821
 
 
1822
        bool unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
 
1823
        Assert(unmapped); NOREF(unmapped);
 
1824
    }
 
1825
 
 
1826
    vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 
1827
}
 
1828
 
 
1829
#if 0
 
1830
void VBoxVHWASurfaceBase::synch(const QRect * aRect)
 
1831
{
 
1832
    synchFB(aRect);
 
1833
    synchTex(aRect);
 
1834
    synchMem(aRect);
 
1835
}
 
1836
 
 
1837
void VBoxVHWASurfaceBase::synchFB(const QRect * pRect)
 
1838
{
 
1839
    Assert(isYInverted());
 
1840
 
 
1841
    if(pRect)
 
1842
    {
 
1843
        Assert(mRect.contains(*pRect));
 
1844
    }
 
1845
 
 
1846
    synchTexMem(pRect);
 
1847
 
 
1848
    if(mUpdateTex2FBRect.isClear())
 
1849
        return;
 
1850
 
 
1851
    if(pRect && !mUpdateTex2FBRect.rect().intersects(*pRect))
 
1852
        return;
 
1853
 
 
1854
    mState->makeCurrent(this);
 
1855
 
 
1856
    VBOXQGL_CHECKERR(
 
1857
            glBindTexture(GL_TEXTURE_2D, mTexture);
 
1858
            );
 
1859
 
 
1860
    VBoxVHWAGlProgramMngr * pMngr = getGlProgramMngr();
 
1861
    pMngr->stopCurrentProgram();
 
1862
 
 
1863
    doTex2FB(&mUpdateTex2FBRect.rect(), &mUpdateTex2FBRect.rect());
 
1864
 
 
1865
    mUpdateTex2FBRect.clear();
 
1866
    Assert(mUpdateTex2FBRect.isClear());
 
1867
}
 
1868
 
 
1869
void VBoxVHWASurfaceBase::synchMem(const QRect * pRect)
 
1870
{
 
1871
    if(pRect)
 
1872
    {
 
1873
        Assert(mRect.contains(*pRect));
 
1874
    }
 
1875
 
 
1876
    if(mUpdateFB2MemRect.isClear())
 
1877
        return;
 
1878
 
 
1879
    if(pRect && !mUpdateFB2MemRect.rect().intersects(*pRect))
 
1880
        return;
 
1881
 
 
1882
    mState->makeYInvertedCurrent(this);
 
1883
//    mState->makeCurrent(this);
 
1884
 
 
1885
    uchar * address = pointAddress(mUpdateFB2MemRect.rect().x(), mUpdateFB2MemRect.rect().y());
 
1886
 
 
1887
    VBOXQGL_CHECKERR(
 
1888
            glPixelStorei(GL_PACK_ROW_LENGTH, mRect.width());
 
1889
            );
 
1890
    VBOXQGL_CHECKERR(
 
1891
            glReadPixels(
 
1892
                mUpdateFB2MemRect.rect().x(),
 
1893
                mUpdateFB2MemRect.rect().y(),
 
1894
                mUpdateFB2MemRect.rect().width(),
 
1895
                mUpdateFB2MemRect.rect().height(),
 
1896
                mColorFormat.format(),
 
1897
                mColorFormat.type(),
 
1898
                address);
 
1899
            );
 
1900
 
 
1901
    mUpdateFB2MemRect.clear();
 
1902
    Assert(mUpdateFB2TexRect.isClear());
 
1903
}
 
1904
 
 
1905
int VBoxVHWASurfaceBase::performBlt(const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool blt)
 
1906
{
 
1907
//    pDstCKey = NULL;
 
1908
//    pSrcCKey = NULL;
 
1909
 
 
1910
    GLuint tex = pSrcSurface->textureSynched(pSrcRect);
 
1911
 
 
1912
    if(pDstCKey)
 
1913
    {
 
1914
        synchTex(pDstRect);
 
1915
    }
 
1916
 
 
1917
    mState->makeCurrent(this, blt);
 
1918
 
 
1919
    VBoxVHWAGlProgramMngr * pMngr = getGlProgramMngr();
 
1920
    VBoxVHWAGlProgramVHWA * pProgram = pMngr->getProgram(pSrcCKey != NULL, &pSrcSurface->colorFormat(), &colorFormat());
 
1921
    if(pProgram)
 
1922
    {
 
1923
        if(pSrcCKey != NULL)
 
1924
        {
 
1925
            pProgram->start();
 
1926
            setCKey(pProgram, &pSrcSurface->colorFormat(), pSrcCKey);
 
1927
 
 
1928
            vboxglActiveTexture(GL_TEXTURE0);
 
1929
        }
 
1930
    }
 
1931
    else
 
1932
    {
 
1933
        pMngr->stopCurrentProgram();
 
1934
    }
 
1935
 
 
1936
//    if(blt)
 
1937
    {
 
1938
        VBOXQGL_CHECKERR(
 
1939
                glBindTexture(GL_TEXTURE_2D, tex);
 
1940
                );
 
1941
 
 
1942
        //TODO: setup strething params
 
1943
        GLsizei wdt = pSrcSurface->mTexRect.width();
 
1944
        GLsizei hgt = pSrcSurface->mTexRect.height();
 
1945
 
 
1946
        VBOXQGL_CHECKERR(
 
1947
                glMatrixMode(GL_TEXTURE);
 
1948
                );
 
1949
        VBOXQGL_CHECKERR(
 
1950
                glPushMatrix();
 
1951
            );
 
1952
 
 
1953
        VBoxGLWidget::doSetupMatrix(QSize(wdt, hgt), true);
 
1954
        VBOXQGL_CHECKERR(
 
1955
                glMatrixMode(GL_MODELVIEW);
 
1956
                );
 
1957
 
 
1958
        doTex2FB(pDstRect, pSrcRect);
 
1959
 
 
1960
        VBOXQGL_CHECKERR(
 
1961
                glMatrixMode(GL_TEXTURE);
 
1962
                );
 
1963
        VBOXQGL_CHECKERR(
 
1964
                glPopMatrix();
 
1965
                );
 
1966
        VBOXQGL_CHECKERR(
 
1967
                glMatrixMode(GL_MODELVIEW);
 
1968
                );
 
1969
    }
 
1970
//    else
 
1971
//    {
 
1972
//
 
1973
//    }
 
1974
 
 
1975
    /* if dst color key */
 
1976
    /* setup ckey shader */
 
1977
    if(pDstCKey)
 
1978
    {
 
1979
        VBOXQGL_CHECKERR(
 
1980
                glBindTexture(GL_TEXTURE_2D, mTexture);
 
1981
                );
 
1982
        pProgram = pMngr->getProgram(true, NULL, NULL);
 
1983
        /* setup ckey values*/
 
1984
        setCKey(pProgram, &colorFormat(), pDstCKey);
 
1985
        pProgram->start();
 
1986
        doTex2FB(pDstRect, pDstRect);
 
1987
    }
 
1988
 
 
1989
    return VINF_SUCCESS;
 
1990
}
 
1991
 
 
1992
int VBoxVHWASurfaceBase::overlay(VBoxVHWASurfaceBase * pOverlaySurface)
 
1993
{
 
1994
    VBOXQGLLOG(("overlay src(0x%x) ", pOverlaySurface));
 
1995
    VBOXQGLLOG_QRECT("dst: ", &pOverlaySurface->mTargRect, "\n");
 
1996
    VBOXQGLLOG_QRECT("src: ", &pOverlaySurface->mSrcRect,  "\n");
 
1997
    VBOXQGLLOG_METHODTIME("time:");
 
1998
 
 
1999
    Assert(!pOverlaySurface->isHidden());
 
2000
 
 
2001
    if(pOverlaySurface->isHidden())
 
2002
    {
 
2003
        VBOXQGLLOG(("!!!hidden!!!\n"));
 
2004
        return VINF_SUCCESS;
 
2005
    }
 
2006
 
 
2007
    const QRect * pSrcRect = &pOverlaySurface->mSrcRect;
 
2008
    const QRect * pDstRect = &pOverlaySurface->mTargRect;
 
2009
    const VBoxVHWAColorKey * pSrcCKey = pOverlaySurface->srcOverlayCKey();
 
2010
    /* we use src (overlay) surface to maintain overridden dst ckey info
 
2011
     * to allow multiple overlays have different overridden dst keys for one primary surface */
 
2012
    /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
 
2013
     * dst ckey value in defaultDstOverlayCKey
 
2014
     * this allows the NULL to be a valid overridden value as well */
 
2015
    const VBoxVHWAColorKey * pDstCKey = pOverlaySurface->dstOverlayCKey() ? pOverlaySurface->defaultDstOverlayCKey() : dstOverlayCKey();
 
2016
 
 
2017
    return performBlt(pDstRect, pOverlaySurface, pSrcRect, pDstCKey, pSrcCKey, false);
 
2018
}
 
2019
 
 
2020
int VBoxVHWASurfaceBase::blt(const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey)
 
2021
{
 
2022
    if(pDstRect)
 
2023
    {
 
2024
        Assert(mRect.contains(*pDstRect));
 
2025
    }
 
2026
    else
 
2027
    {
 
2028
        pDstRect = &mRect;
 
2029
    }
 
2030
 
 
2031
    if(pSrcRect)
 
2032
    {
 
2033
        Assert(pSrcSurface->mRect.contains(*pSrcRect));
 
2034
    }
 
2035
    else
 
2036
    {
 
2037
        pSrcRect = &pSrcSurface->mRect;
 
2038
    }
 
2039
 
 
2040
    if(!pSrcCKey)
 
2041
        pSrcCKey = pSrcSurface->srcBltCKey();
 
2042
    if(!pDstCKey)
 
2043
        pDstCKey = dstBltCKey();
 
2044
 
 
2045
    VBOXQGLLOG(("blt dst(0x%x), src(0x%x)", this, pSrcSurface));
 
2046
    VBOXQGLLOG_QRECT("dst: ", pDstRect, "\n");
 
2047
    VBOXQGLLOG_QRECT("src: ", pSrcRect, "\n");
 
2048
    VBOXQGLLOG_METHODTIME("time:");
 
2049
    int rc = performBlt(pDstRect, pSrcSurface, pSrcRect, pDstCKey, pSrcCKey, true);
 
2050
 
 
2051
    mUpdateFB2TexRect.add(*pDstRect);
 
2052
    Assert(!mUpdateFB2TexRect.isClear());
 
2053
    Assert(mRect.contains(mUpdateFB2TexRect.rect()));
 
2054
//    synchTexture(pDstRect);
 
2055
    mUpdateFB2MemRect.add(*pDstRect);
 
2056
    Assert(!mUpdateFB2MemRect.isClear());
 
2057
    Assert(mRect.contains(mUpdateFB2MemRect.rect()));
 
2058
 
 
2059
    return rc;
 
2060
}
 
2061
#endif
 
2062
void VBoxVHWASurfaceBase::doTex2FB(const QRect * pDstRect, const QRect * pSrcRect)
 
2063
{
 
2064
    int tx1, ty1, tx2, ty2;
 
2065
    pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
 
2066
    int bx1, by1, bx2, by2;
 
2067
    pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
 
2068
    tx2++; ty2++;bx2++; by2++;
 
2069
 
 
2070
#if 1
 
2071
//    VBOXQGL_CHECKERR(
 
2072
            VBOXQGLLOG_QRECT("texRect: ", &mpTex[0]->texRect(), "\n");
 
2073
            glBegin(GL_QUADS);
 
2074
//            glTexCoord2d(((double)tx1)/mpTex[0]->texRect().width(), ((double)ty1)/mpTex[0]->texRect().height());
 
2075
//            glVertex2i(bx1, by1);
 
2076
//            glTexCoord2d(((double)tx1)/mpTex[0]->texRect().width(), ((double)ty2)/mpTex[0]->texRect().height());
 
2077
//            glVertex2i(bx1, by2);
 
2078
//            glTexCoord2d(((double)tx2)/mpTex[0]->texRect().width(), ((double)ty2)/mpTex[0]->texRect().height());
 
2079
//            glVertex2i(bx2, by2);
 
2080
//            glTexCoord2d(((double)tx2)/mpTex[0]->texRect().width(), ((double)ty1)/mpTex[0]->texRect().height());
 
2081
//            glVertex2i(bx2, by1);
 
2082
            mpTex[0]->texCoord(tx1, ty1);
 
2083
            glVertex2i(bx1, by1);
 
2084
            mpTex[0]->texCoord(tx1, ty2);
 
2085
            glVertex2i(bx1, by2);
 
2086
            mpTex[0]->texCoord(tx2, ty2);
 
2087
            glVertex2i(bx2, by2);
 
2088
            mpTex[0]->texCoord(tx2, ty1);
 
2089
            glVertex2i(bx2, by1);
 
2090
 
 
2091
            glEnd();
 
2092
//            );
 
2093
#else
 
2094
        glBegin(GL_QUADS);
 
2095
        glTexCoord2d(0.0, 0.0);
 
2096
        glVertex2i(0, 0);
 
2097
        glTexCoord2d(0.0, 1.0);
 
2098
        glVertex2i(0, mRect.height());
 
2099
        glTexCoord2d(1.0, 1.0);
 
2100
        glVertex2i(mRect.width(), mRect.height());
 
2101
        glTexCoord2d(1.0, 0.0);
 
2102
        glVertex2i(mRect.width(), 0);
 
2103
        glEnd();
 
2104
#endif
 
2105
}
 
2106
 
 
2107
 
 
2108
void VBoxVHWASurfaceBase::doMultiTex2FB(const QRect * pDstRect, const QRect * pSrcRect, int cSrcTex)
 
2109
{
 
2110
    int tx1, ty1, tx2, ty2;
 
2111
    pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
 
2112
    int bx1, by1, bx2, by2;
 
2113
    pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
 
2114
    tx2++; ty2++;bx2++; by2++;
 
2115
    uint32_t t0width = mpTex[0]->rect().width();
 
2116
    uint32_t t0height = mpTex[0]->rect().height();
 
2117
 
 
2118
//    VBOXQGL_CHECKERR(
 
2119
            glBegin(GL_QUADS);
 
2120
            for(int i = 0; i < cSrcTex; i++)
 
2121
            {
 
2122
//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx1)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
 
2123
//                        ((double)ty1)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
 
2124
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx1/(t0width/mpTex[i]->texRect().width()), ty1/(t0height/mpTex[i]->rect().height()));
 
2125
            }
 
2126
            glVertex2i(bx1, by1);
 
2127
            for(int i = 0; i < cSrcTex; i++)
 
2128
            {
 
2129
//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx1)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
 
2130
//                        ((double)ty2)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
 
2131
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx1/(t0width/mpTex[i]->texRect().width()), ty2/(t0height/mpTex[i]->rect().height()));
 
2132
            }
 
2133
            glVertex2i(bx1, by2);
 
2134
            for(int i = 0; i < cSrcTex; i++)
 
2135
            {
 
2136
//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx2)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
 
2137
//                        ((double)ty2)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
 
2138
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx2/(t0width/mpTex[i]->texRect().width()), ty2/(t0height/mpTex[i]->rect().height()));
 
2139
 
 
2140
            }
 
2141
            glVertex2i(bx2, by2);
 
2142
            for(int i = 0; i < cSrcTex; i++)
 
2143
            {
 
2144
//                vboxglMultiTexCoord2d(GL_TEXTURE0 + i, ((double)tx2)/mpTex[i]->texRect().width()/(width()/mpTex[i]->rect().width()),
 
2145
//                        ((double)ty1)/mpTex[i]->texRect().height()/(height()/mpTex[i]->rect().height()));
 
2146
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx2/(t0width/mpTex[i]->texRect().width()), ty1/(t0height/mpTex[i]->rect().height()));
 
2147
            }
 
2148
            glVertex2i(bx2, by1);
 
2149
            glEnd();
 
2150
//            );
 
2151
}
 
2152
 
 
2153
void VBoxVHWASurfaceBase::doMultiTex2FB(const QRect * pDstRect, VBoxVHWATexture * pDstTex, const QRect * pSrcRect, int cSrcTex)
 
2154
{
 
2155
    int tx1, ty1, tx2, ty2;
 
2156
    pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
 
2157
    int bx1, by1, bx2, by2;
 
2158
    pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
 
2159
    tx2++; ty2++;bx2++; by2++;
 
2160
    uint32_t t0width = mpTex[0]->rect().width();
 
2161
    uint32_t t0height = mpTex[0]->rect().height();
 
2162
 
 
2163
//    VBOXQGL_CHECKERR(
 
2164
            glBegin(GL_QUADS);
 
2165
 
 
2166
            for(int i = 0; i < cSrcTex; i++)
 
2167
            {
 
2168
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx1/(t0width/mpTex[i]->rect().width()), ty1/(t0height/mpTex[i]->rect().height()));
 
2169
            }
 
2170
            pDstTex->multiTexCoord(GL_TEXTURE0 + cSrcTex, bx1, by1);
 
2171
            glVertex2i(bx1, by1);
 
2172
 
 
2173
            for(int i = 0; i < cSrcTex; i++)
 
2174
            {
 
2175
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx1/(t0width/mpTex[i]->rect().width()), ty2/(t0height/mpTex[i]->rect().height()));
 
2176
            }
 
2177
            pDstTex->multiTexCoord(GL_TEXTURE0 + cSrcTex, bx1, by2);
 
2178
            glVertex2i(bx1, by2);
 
2179
 
 
2180
            for(int i = 0; i < cSrcTex; i++)
 
2181
            {
 
2182
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx2/(t0width/mpTex[i]->rect().width()), ty2/(t0height/mpTex[i]->rect().height()));
 
2183
            }
 
2184
            pDstTex->multiTexCoord(GL_TEXTURE0 + cSrcTex, bx2, by2);
 
2185
            glVertex2i(bx2, by2);
 
2186
 
 
2187
            for(int i = 0; i < cSrcTex; i++)
 
2188
            {
 
2189
                mpTex[i]->multiTexCoord(GL_TEXTURE0 + i, tx2/(t0width/mpTex[i]->rect().width()), ty1/(t0height/mpTex[i]->rect().height()));
 
2190
            }
 
2191
            pDstTex->multiTexCoord(GL_TEXTURE0 + cSrcTex, bx2, by1);
 
2192
            glVertex2i(bx2, by1);
 
2193
 
 
2194
            glEnd();
 
2195
//            );
 
2196
 
 
2197
}
 
2198
 
 
2199
int VBoxVHWASurfaceBase::lock(const QRect * pRect, uint32_t flags)
 
2200
{
 
2201
    Q_UNUSED(flags);
 
2202
 
 
2203
    if(pRect)
 
2204
    {
 
2205
        Assert(mRect.contains(*pRect));
 
2206
    }
 
2207
 
 
2208
    Assert(mLockCount >= 0);
 
2209
    if(pRect && pRect->isEmpty())
 
2210
        return VERR_GENERAL_FAILURE;
 
2211
    if(mLockCount < 0)
 
2212
        return VERR_GENERAL_FAILURE;
 
2213
 
 
2214
    VBOXQGLLOG(("lock (0x%x)", this));
 
2215
    VBOXQGLLOG_QRECT("rect: ", pRect ? pRect : &mRect, "\n");
 
2216
    VBOXQGLLOG_METHODTIME("time ");
 
2217
//    if(!(flags & VBOXVHWA_LOCK_DISCARDCONTENTS))
 
2218
//    {
 
2219
//        synchMem(pRect);
 
2220
//    }
 
2221
 
 
2222
    mUpdateMem2TexRect.add(pRect ? *pRect : mRect);
 
2223
 
 
2224
    Assert(!mUpdateMem2TexRect.isClear());
 
2225
    Assert(mRect.contains(mUpdateMem2TexRect.rect()));
 
2226
    return VINF_SUCCESS;
 
2227
}
 
2228
 
 
2229
int VBoxVHWASurfaceBase::unlock()
 
2230
{
 
2231
    VBOXQGLLOG(("unlock (0x%x)\n", this));
 
2232
    mLockCount = 0;
 
2233
    return VINF_SUCCESS;
 
2234
}
 
2235
 
 
2236
void VBoxVHWASurfaceBase::setRectValues (const QRect & aTargRect, const QRect & aSrcRect)
 
2237
{
 
2238
    mTargRect = aTargRect;
 
2239
    mSrcRect = aSrcRect;
 
2240
}
 
2241
 
 
2242
void VBoxVHWASurfaceBase::setVisibleRectValues (const QRect & aVisTargRect)
 
2243
{
 
2244
    mVisibleTargRect = aVisTargRect.intersected(mTargRect);
 
2245
    if(mVisibleTargRect.isEmpty() || mTargRect.isEmpty())
 
2246
    {
 
2247
        mVisibleSrcRect.setSize(QSize(0, 0));
 
2248
    }
 
2249
    else
 
2250
    {
 
2251
        float stretchX = float(mSrcRect.width()) / mTargRect.width();
 
2252
        float stretchY = float(mSrcRect.height()) / mTargRect.height();
 
2253
        int tx1, tx2, ty1, ty2, vtx1, vtx2, vty1, vty2;
 
2254
        int sx1, sx2, sy1, sy2;
 
2255
        mVisibleTargRect.getCoords(&vtx1, &vty1, &vtx2, &vty2);
 
2256
        mTargRect.getCoords(&tx1, &ty1, &tx2, &ty2);
 
2257
        mSrcRect.getCoords(&sx1, &sy1, &sx2, &sy2);
 
2258
        int dx1 = vtx1 - tx1;
 
2259
        int dy1 = vty1 - ty1;
 
2260
        int dx2 = vtx2 - tx2;
 
2261
        int dy2 = vty2 - ty2;
 
2262
        int vsx1, vsy1, vsx2, vsy2;
 
2263
        Assert(dx1 >= 0);
 
2264
        Assert(dy1 >= 0);
 
2265
        Assert(dx2 <= 0);
 
2266
        Assert(dy2 <= 0);
 
2267
        vsx1 = sx1 + int(dx1*stretchX);
 
2268
        vsy1 = sy1 + int(dy1*stretchY);
 
2269
        vsx2 = sx2 + int(dx2*stretchX);
 
2270
        vsy2 = sy2 + int(dy2*stretchY);
 
2271
        mVisibleSrcRect.setCoords(vsx1, vsy1, vsx2, vsy2);
 
2272
        Assert(!mVisibleSrcRect.isEmpty());
 
2273
        Assert(mSrcRect.contains(mVisibleSrcRect));
 
2274
    }
 
2275
}
 
2276
 
 
2277
 
 
2278
void VBoxVHWASurfaceBase::setRects(const QRect & aTargRect, const QRect & aSrcRect)
 
2279
{
 
2280
    if(mTargRect != aTargRect || mSrcRect != aSrcRect)
 
2281
    {
 
2282
        setRectValues(aTargRect, aSrcRect);
 
2283
        mNeedVisibilityReinit = true;
 
2284
    }
 
2285
}
 
2286
 
 
2287
void VBoxVHWASurfaceBase::setTargRectPosition(const QPoint & aPoint)
 
2288
{
 
2289
    QRect tRect = targRect();
 
2290
    tRect.moveTopLeft(aPoint);
 
2291
    setRects(tRect, srcRect());
 
2292
}
 
2293
 
 
2294
void VBoxVHWASurfaceBase::updateVisibility (VBoxVHWASurfaceBase *pPrimary, const QRect & aVisibleTargRect, bool bNotIntersected, bool bForce)
 
2295
{
 
2296
    if(mNeedVisibilityReinit || bForce || aVisibleTargRect.intersected(mTargRect) != mVisibleTargRect || mNotIntersected != bNotIntersected)
 
2297
    {
 
2298
        setVisibleRectValues(aVisibleTargRect);
 
2299
        mNotIntersected = bNotIntersected;
 
2300
        initDisplay(pPrimary);
 
2301
        mNeedVisibilityReinit = false;
 
2302
    }
 
2303
}
 
2304
 
 
2305
void VBoxVHWASurfaceBase::deleteDisplay(
 
2306
//        bool bInverted
 
2307
        )
 
2308
{
 
2309
    if(mVisibleDisplayInitialized)
 
2310
    {
 
2311
#ifdef VBOXVHWA_USE_TEXGROUP
 
2312
        for(int i = mpTex.numSets()-1; i >=0; --i)
 
2313
        {
 
2314
        if(mpTex.display())
 
2315
        {
 
2316
            glDeleteLists(mpTex.display(), 1);
 
2317
            mpTex.display() = 0;
 
2318
        }
 
2319
        if(mpProgram)
 
2320
        {
 
2321
            mpProgram = NULL;
 
2322
        }
 
2323
        mpTex.swap();
 
2324
        }
 
2325
#else
 
2326
        if(mVisibleDisplay)
 
2327
        {
 
2328
            glDeleteLists(mVisibleDisplay, 1);
 
2329
            mVisibleDisplay = 0;
 
2330
        }
 
2331
        if(mpProgram)
 
2332
        {
 
2333
            mpProgram = NULL;
 
2334
        }
 
2335
#endif
 
2336
        mVisibleDisplayInitialized = false;
 
2337
    }
 
2338
}
 
2339
 
 
2340
void VBoxVHWASurfaceBase::doDisplay(VBoxVHWASurfaceBase *pPrimary, bool bProgram, bool bBindDst)
 
2341
{
 
2342
    bool bInvokeMultiTex2 = false;
 
2343
 
 
2344
    if(bProgram)
 
2345
    {
 
2346
//        pProgram->start();
 
2347
 
 
2348
//            if(pSrcCKey != NULL)
 
2349
//            {
 
2350
//                pProgram->start();
 
2351
//                setCKey(pProgram, &pSrcSurface->colorFormat(), pSrcCKey);
 
2352
 
 
2353
//                vboxglActiveTexture(GL_TEXTURE0);
 
2354
//            }
 
2355
 
 
2356
        if(bBindDst)
 
2357
        {
 
2358
            if(fourcc() == FOURCC_YV12)
 
2359
            {
 
2360
                vboxglActiveTexture(GL_TEXTURE1);
 
2361
                mpTex[1]->bind();
 
2362
                vboxglActiveTexture(GL_TEXTURE1+1);
 
2363
                mpTex[2]->bind();
 
2364
 
 
2365
                vboxglActiveTexture(GL_TEXTURE1+2);
 
2366
            }
 
2367
            else
 
2368
            {
 
2369
                vboxglActiveTexture(GL_TEXTURE1);
 
2370
            }
 
2371
            pPrimary->mpTex[0]->bind();
 
2372
 
 
2373
            vboxglActiveTexture(GL_TEXTURE0);
 
2374
            mpTex[0]->bind();
 
2375
            bInvokeMultiTex2 = true;
 
2376
        }
 
2377
        else
 
2378
        {
 
2379
            if(fourcc() == FOURCC_YV12)
 
2380
            {
 
2381
                vboxglActiveTexture(GL_TEXTURE1);
 
2382
                mpTex[1]->bind();
 
2383
                vboxglActiveTexture(GL_TEXTURE0);
 
2384
            }
 
2385
            mpTex[0]->bind();
 
2386
        }
 
2387
    }
 
2388
    else
 
2389
    {
 
2390
//        vboxglActiveTexture(GL_TEXTURE0);
 
2391
        mpTex[0]->bind();
 
2392
//        VBOXQGLLOG(("binding (primary??) texture: %d\n", mpTex[0]->texture()));
 
2393
    }
 
2394
 
 
2395
    if(bInvokeMultiTex2)
 
2396
    {
 
2397
        doMultiTex2FB(&mVisibleTargRect, pPrimary->mpTex[0], &mVisibleSrcRect,
 
2398
                (fourcc() == FOURCC_YV12) ? 2 : 1);
 
2399
    }
 
2400
    else
 
2401
    {
 
2402
        if(fourcc() == FOURCC_YV12)
 
2403
        {
 
2404
            doMultiTex2FB(&mVisibleTargRect, &mVisibleSrcRect, 2);
 
2405
        }
 
2406
        else
 
2407
        {
 
2408
            VBOXQGLLOG_QRECT("mVisibleTargRect: ", &mVisibleTargRect, "\n");
 
2409
            VBOXQGLLOG_QRECT("mVisibleSrcRect: ", &mVisibleSrcRect, "\n");
 
2410
            doTex2FB(&mVisibleTargRect, &mVisibleSrcRect);
 
2411
        }
 
2412
    }
 
2413
 
 
2414
//    if(pProgram)
 
2415
//    {
 
2416
//        pProgram->stop();
 
2417
//    }
 
2418
}
 
2419
 
 
2420
class VBoxVHWAGlProgramVHWA * VBoxVHWASurfaceBase::calcProgram(VBoxVHWASurfaceBase * pPrimary)
 
2421
{
 
2422
    const VBoxVHWAColorKey * pSrcCKey = NULL, *pDstCKey = NULL;
 
2423
    uint32_t type = 0;
 
2424
 
 
2425
    pSrcCKey = getActiveSrcOverlayCKey();
 
2426
    /* we use src (overlay) surface to maintain overridden dst ckey info
 
2427
     * to allow multiple overlays have different overridden dst keys for one primary surface */
 
2428
    /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
 
2429
     * dst ckey value in defaultDstOverlayCKey
 
2430
     * this allows the NULL to be a valid overridden value as well */
 
2431
    pDstCKey = getActiveDstOverlayCKey(pPrimary);
 
2432
 
 
2433
    if(pDstCKey != NULL)
 
2434
        type |= VBOXVHWA_PROGRAM_DSTCOLORKEY;
 
2435
    if(pSrcCKey)
 
2436
        type |= VBOXVHWA_PROGRAM_SRCCOLORKEY;
 
2437
    if((pDstCKey || pSrcCKey) && mNotIntersected)
 
2438
        type |= VBOXVHWA_PROGRAM_COLORKEYNODISCARD;
 
2439
 
 
2440
    return mWidget->vboxVHWAGetGlProgramMngr()->getProgram(type, &colorFormat(), &pPrimary->colorFormat());
 
2441
}
 
2442
 
 
2443
int VBoxVHWASurfaceBase::createDisplay(VBoxVHWASurfaceBase *pPrimary, GLuint *pDisplay, class VBoxVHWAGlProgramVHWA ** ppProgram)
 
2444
{
 
2445
    if(mVisibleTargRect.isEmpty())
 
2446
    {
 
2447
        Assert(mVisibleSrcRect.isEmpty());
 
2448
        return 0;
 
2449
    }
 
2450
    Assert(!mVisibleSrcRect.isEmpty());
 
2451
    /* just for the fallback */
 
2452
    if(mVisibleSrcRect.isEmpty())
 
2453
    {
 
2454
        *pDisplay = 0;
 
2455
        return VINF_SUCCESS;
 
2456
    }
 
2457
 
 
2458
    VBoxVHWAGlProgramVHWA * pProgram = NULL;
 
2459
    if(pPrimary)
 
2460
    {
 
2461
        pProgram = calcProgram(pPrimary);
 
2462
        if(pProgram)
 
2463
        {
 
2464
            const VBoxVHWAColorKey *pResSrcCKey = getActiveSrcOverlayCKey();
 
2465
            const VBoxVHWAColorKey *pResDstCKey = getActiveDstOverlayCKey(pPrimary);
 
2466
 
 
2467
            pProgram->start();
 
2468
            if(pResSrcCKey)
 
2469
            {
 
2470
                VBoxVHWASurfaceBase::setCKey(pProgram, &colorFormat(), pResSrcCKey, false);
 
2471
            }
 
2472
            if(pResDstCKey)
 
2473
            {
 
2474
                VBoxVHWASurfaceBase::setCKey(pProgram, &pPrimary->colorFormat(), pResDstCKey, true);
 
2475
            }
 
2476
            pProgram->stop();
 
2477
        }
 
2478
    }
 
2479
 
 
2480
    glGetError(); /* clear the err flag */
 
2481
    GLuint display = glGenLists(1);
 
2482
    GLenum err = glGetError();
 
2483
    if(err == GL_NO_ERROR)
 
2484
    {
 
2485
        Assert(display);
 
2486
        if(!display)
 
2487
        {
 
2488
            /* well, it seems it should not return 0 on success according to the spec,
 
2489
             * but just in case, pick another one */
 
2490
            display = glGenLists(1);
 
2491
            err = glGetError();
 
2492
            if(err == GL_NO_ERROR)
 
2493
            {
 
2494
                Assert(display);
 
2495
            }
 
2496
            else
 
2497
            {
 
2498
                /* we are failed */
 
2499
                Assert(!display);
 
2500
                display = 0;
 
2501
            }
 
2502
        }
 
2503
 
 
2504
        if(display)
 
2505
        {
 
2506
            const VBoxVHWAColorKey * pDstCKey = pPrimary ? getActiveDstOverlayCKey(pPrimary) : NULL;
 
2507
 
 
2508
            glNewList(display, GL_COMPILE);
 
2509
 
 
2510
            doDisplay(pPrimary, pProgram != 0, pDstCKey != NULL);
 
2511
 
 
2512
            glEndList();
 
2513
            VBOXQGL_ASSERTNOERR();
 
2514
            *pDisplay = display;
 
2515
            *ppProgram = pProgram;
 
2516
            return VINF_SUCCESS;
 
2517
        }
 
2518
    }
 
2519
    else
 
2520
    {
 
2521
        VBOXQGLLOG(("gl error ocured (0x%x)\n", err));
 
2522
        Assert(err == GL_NO_ERROR);
 
2523
    }
 
2524
 
 
2525
    return VERR_GENERAL_FAILURE;
 
2526
}
 
2527
 
 
2528
void VBoxVHWASurfaceBase::initDisplay(VBoxVHWASurfaceBase *pPrimary)
 
2529
{
 
2530
    deleteDisplay();
 
2531
 
 
2532
    int rc;
 
2533
#ifdef VBOXVHWA_USE_TEXGROUP
 
2534
    for(int i = mpTex.numSets()-1; i >=0; --i)
 
2535
    {
 
2536
        rc = createDisplay(pPrimary, &mpTex.display(), &mpProgram);
 
2537
        AssertRC(rc);
 
2538
        if(RT_FAILURE(rc))
 
2539
            break;
 
2540
        mpTex.swap();
 
2541
    }
 
2542
#else
 
2543
    rc = createDisplay(pPrimary, &mVisibleDisplay, &mpProgram);
 
2544
    AssertRC(rc);
 
2545
#endif
 
2546
    if(RT_SUCCESS(rc))
 
2547
    {
 
2548
        mVisibleDisplayInitialized = true;
 
2549
    }
 
2550
    else
 
2551
    {
 
2552
        mVisibleDisplayInitialized = false;
 
2553
    }
 
2554
}
 
2555
 
 
2556
void VBoxVHWASurfaceBase::updatedMem(const QRect *rec)
 
2557
{
 
2558
    if(rec)
 
2559
    {
 
2560
        Assert(mRect.contains(*rec));
 
2561
    }
 
2562
    mUpdateMem2TexRect.add(*rec);
 
2563
}
 
2564
 
 
2565
//void VBoxVHWASurfaceBase::setVisibleTargetRect(const QRect & aRect)
 
2566
//{
 
2567
//    Assert(mVisibleRect.contains(aRect));
 
2568
//    mVisibleRect = mSrcRect.intersected(aRect);
 
2569
//}
 
2570
 
 
2571
bool VBoxVHWASurfaceBase::performDisplay(VBoxVHWASurfaceBase *pPrimary, bool bForce)
 
2572
{
 
2573
    Assert(mVisibleDisplayInitialized);
 
2574
 
 
2575
#ifdef VBOXVHWA_USE_TEXGROUP
 
2576
    if(mpTex.display() == 0)
 
2577
#else
 
2578
    if(mVisibleDisplay == 0)
 
2579
#endif
 
2580
    {
 
2581
        /* nothing to display, i.e. the surface is not visible,
 
2582
         * in the sense that it's located behind the viewport ranges */
 
2583
        Assert(mVisibleSrcRect.isEmpty());
 
2584
        Assert(mVisibleTargRect.isEmpty());
 
2585
        return false;
 
2586
    }
 
2587
    else
 
2588
    {
 
2589
        Assert(!mVisibleSrcRect.isEmpty());
 
2590
        Assert(!mVisibleTargRect.isEmpty());
 
2591
    }
 
2592
 
 
2593
    bForce |= synchTexMem(&mVisibleSrcRect);
 
2594
    if(pPrimary && getActiveDstOverlayCKey(pPrimary))
 
2595
    {
 
2596
        bForce |= pPrimary->synchTexMem(&mVisibleTargRect);
 
2597
    }
 
2598
 
 
2599
    if(!bForce)
 
2600
        return false;
 
2601
 
 
2602
#ifdef VBOXVHWA_USE_TEXGROUP
 
2603
    Assert(mpTex.display());
 
2604
#else
 
2605
    Assert(mVisibleDisplay);
 
2606
#endif
 
2607
 
 
2608
    if(!mVisibleDisplayInitialized)
 
2609
    {
 
2610
        VBoxVHWAGlProgramVHWA * pProgram = NULL;
 
2611
        if(pPrimary)
 
2612
        {
 
2613
            pProgram = calcProgram(pPrimary);
 
2614
        }
 
2615
 
 
2616
        const VBoxVHWAColorKey * pDstCKey = NULL;
 
2617
        pDstCKey = getActiveDstOverlayCKey(pPrimary);
 
2618
 
 
2619
        if(pProgram)
 
2620
            pProgram->start();
 
2621
        doDisplay(pPrimary, pProgram != 0, pDstCKey != NULL);
 
2622
        if(pProgram)
 
2623
            pProgram->stop();
 
2624
 
 
2625
 
 
2626
//        doDisplay(pPrimary, NULL, false);
 
2627
    }
 
2628
    else
 
2629
    {
 
2630
        if(mpProgram)
 
2631
            mpProgram->start();
 
2632
#ifdef VBOXVHWA_USE_TEXGROUP
 
2633
        VBOXQGL_CHECKERR(
 
2634
                glCallList(mpTex.display());
 
2635
                );
 
2636
#else
 
2637
        VBOXQGL_CHECKERR(
 
2638
                glCallList(mVisibleDisplay);
 
2639
                );
 
2640
#endif
 
2641
        if(mpProgram)
 
2642
            mpProgram->stop();
 
2643
 
 
2644
    }
 
2645
 
 
2646
    Assert(bForce);
 
2647
    return true;
 
2648
}
 
2649
 
 
2650
class VBoxGLContext : public QGLContext
 
2651
{
 
2652
public:
 
2653
    VBoxGLContext (const QGLFormat & format ) :
 
2654
        QGLContext(format),
 
2655
        mAllowDoneCurrent(true)
 
2656
    {
 
2657
    }
 
2658
 
 
2659
    void doneCurrent()
 
2660
    {
 
2661
        if(!mAllowDoneCurrent)
 
2662
            return;
 
2663
        QGLContext::doneCurrent();
 
2664
    }
 
2665
 
 
2666
    bool isDoneCurrentAllowed() { return mAllowDoneCurrent; }
 
2667
    void allowDoneCurrent(bool bAllow) { mAllowDoneCurrent = bAllow; }
 
2668
private:
 
2669
    bool mAllowDoneCurrent;
 
2670
};
 
2671
 
 
2672
VBoxGLWidget::VBoxGLWidget (VBoxConsoleView *aView, QWidget *aParent)
 
2673
    : QGLWidget (new VBoxGLContext(VBoxGLWidget::vboxGLFormat()), aParent),
 
2674
    mSurfHandleTable(128), /* 128 should be enough */
 
2675
    mpfnOp(NULL),
 
2676
    mOpContext(NULL),
 
2677
    mPixelFormat(0),
 
2678
    mUsesGuestVRAM(false),
 
2679
    mRepaintNeeded(false),
 
2680
//    mbVGASurfCreated(false),
 
2681
    mView(aView),
 
2682
    mConstructingList(NULL),
 
2683
    mcRemaining2Contruct(0)
 
2684
#ifdef VBOXVHWA_PROFILE_FPS
 
2685
    ,
 
2686
    mFPSCounter(64),
 
2687
    mbNewFrame(false)
 
2688
#endif
 
2689
{
 
2690
    mpMngr = new VBoxVHWAGlProgramMngr();
 
2691
//        /* No need for background drawing */
 
2692
//        setAttribute (Qt::WA_OpaquePaintEvent);
 
2693
}
 
2694
 
 
2695
const QGLFormat & VBoxGLWidget::vboxGLFormat()
 
2696
{
 
2697
    static QGLFormat vboxFormat = QGLFormat();
 
2698
    vboxFormat.setAlpha(true);
 
2699
    Assert(vboxFormat.alpha());
 
2700
    vboxFormat.setSwapInterval(0);
 
2701
    Assert(vboxFormat.swapInterval() == 0);
 
2702
    vboxFormat.setAccum(false);
 
2703
    Assert(!vboxFormat.accum());
 
2704
    vboxFormat.setDepth(false);
 
2705
    Assert(!vboxFormat.depth());
 
2706
//  vboxFormat.setRedBufferSize(8);
 
2707
//  vboxFormat.setGreenBufferSize(8);
 
2708
//  vboxFormat.setBlueBufferSize(8);
 
2709
    return vboxFormat;
 
2710
}
 
2711
 
 
2712
VBoxGLWidget::~VBoxGLWidget()
 
2713
{
 
2714
    delete mpMngr;
 
2715
}
 
2716
 
 
2717
#ifdef VBOXVHWA_OLD_COORD
 
2718
void VBoxGLWidget::doSetupMatrix(const QSize & aSize, bool bInverted)
 
2719
{
 
2720
    VBOXQGL_CHECKERR(
 
2721
            glLoadIdentity();
 
2722
            );
 
2723
    if(bInverted)
 
2724
    {
 
2725
        VBOXQGL_CHECKERR(
 
2726
                glScalef(1.0f/aSize.width(), 1.0f/aSize.height(), 1.0f);
 
2727
                );
 
2728
    }
 
2729
    else
 
2730
    {
 
2731
        /* make display coordinates be scaled to pixel coordinates */
 
2732
        VBOXQGL_CHECKERR(
 
2733
                glTranslatef(0.0f, 1.0f, 0.0f);
 
2734
                );
 
2735
        VBOXQGL_CHECKERR(
 
2736
                glScalef(1.0f/aSize.width(), 1.0f/aSize.height(), 1.0f);
 
2737
                );
 
2738
        VBOXQGL_CHECKERR(
 
2739
                glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
 
2740
                );
 
2741
    }
 
2742
}
 
2743
#endif
 
2744
 
 
2745
void VBoxGLWidget::adjustViewport(const QSize &display, const QRect &viewport)
 
2746
{
 
2747
#ifdef VBOXVHWA_OLD_COORD
 
2748
    /* viewport:  (viewport.x;viewport.y) (viewport.width;viewport.height)*/
 
2749
    glViewport(-((int)display.width() + viewport.x()),
 
2750
                -((int)display.height() - viewport.y() + display.height() - viewport.height()),
 
2751
                2*display.width(),
 
2752
                2*display.height());
 
2753
#else
 
2754
    glViewport(-viewport.x(),
 
2755
                   viewport.height() + viewport.y() - display.height(),
 
2756
               display.width(),
 
2757
               display.height());
 
2758
 
 
2759
#endif
 
2760
}
 
2761
 
 
2762
void VBoxGLWidget::setupMatricies(const QSize &display)
 
2763
{
 
2764
#ifdef VBOXVHWA_OLD_COORD
 
2765
    glMatrixMode(GL_PROJECTION);
 
2766
    glLoadIdentity();
 
2767
    glFrustum(0., (GLdouble)display.width(), 0., (GLdouble)display.height(), 0., 0.);
 
2768
 
 
2769
    glMatrixMode(GL_MODELVIEW);
 
2770
    //    doSetupMatrix(bInverted ? &mRect.size() : &mTargSize.size(), bInverted);
 
2771
    doSetupMatrix(display, false);
 
2772
#else
 
2773
    glMatrixMode(GL_PROJECTION);
 
2774
    glLoadIdentity();
 
2775
    glOrtho(0., (GLdouble)display.width(), (GLdouble)display.height(), 0., -1., 1.);
 
2776
 
 
2777
    glMatrixMode(GL_MODELVIEW);
 
2778
    glLoadIdentity();
 
2779
#endif
 
2780
}
 
2781
 
 
2782
VBoxVHWACommandElement * VBoxGLWidget::processCmdList(VBoxVHWACommandElement * pCmd)
 
2783
{
 
2784
    VBoxVHWACommandElement * pCur;
 
2785
    do
 
2786
    {
 
2787
        pCur = pCmd;
 
2788
        switch(pCmd->type())
 
2789
        {
 
2790
        case VBOXVHWA_PIPECMD_PAINT:
 
2791
            vboxDoUpdateRect(&pCmd->rect());
 
2792
            break;
 
2793
#ifdef VBOX_WITH_VIDEOHWACCEL
 
2794
        case VBOXVHWA_PIPECMD_VHWA:
 
2795
            vboxDoVHWACmd(pCmd->vhwaCmd());
 
2796
            break;
 
2797
        case VBOXVHWA_PIPECMD_OP:
 
2798
        {
 
2799
            const VBOXVHWACALLBACKINFO & info = pCmd->op();
 
2800
            (info.pThis->*(info.pfnCallback))(info.pContext);
 
2801
            break;
 
2802
        }
 
2803
        case VBOXVHWA_PIPECMD_FUNC:
 
2804
        {
 
2805
            const VBOXVHWAFUNCCALLBACKINFO & info = pCmd->func();
 
2806
            info.pfnCallback(info.pContext1, info.pContext2);
 
2807
            break;
 
2808
        }
 
2809
#endif
 
2810
        default:
 
2811
            Assert(0);
 
2812
        }
 
2813
        pCmd = pCmd->mpNext;
 
2814
    } while(pCmd);
 
2815
 
 
2816
    return pCur;
 
2817
}
 
2818
 
 
2819
void VBoxGLWidget::vboxDoProcessVHWACommands(void *pContext)
 
2820
{
 
2821
    VBoxVHWACommandElementProcessor * pPipe = (VBoxVHWACommandElementProcessor*)pContext;
 
2822
    VBoxVHWACommandElement * pFirst = pPipe->detachCmdList(NULL, NULL);
 
2823
    do
 
2824
    {
 
2825
        VBoxVHWACommandElement * pLast = processCmdList(pFirst);
 
2826
 
 
2827
        pFirst = pPipe->detachCmdList(pFirst, pLast);
 
2828
    } while(pFirst);
 
2829
 
 
2830
//    mDisplay.performDisplay();
 
2831
}
 
2832
 
 
2833
int VBoxGLWidget::reset(VHWACommandList * pCmdList)
 
2834
{
 
2835
    VBOXVHWACMD * pCmd;
 
2836
    const OverlayList & overlays = mDisplay.overlays();
 
2837
    for (OverlayList::const_iterator oIt = overlays.begin();
 
2838
            oIt != overlays.end(); ++ oIt)
 
2839
    {
 
2840
        VBoxVHWASurfList * pSurfList = *oIt;
 
2841
        if(pSurfList->current())
 
2842
        {
 
2843
            /* 1. hide overlay */
 
2844
            pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
 
2845
            VBOXVHWACMD_SURF_OVERLAY_UPDATE *pOUCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
 
2846
            pOUCmd->u.in.hSrcSurf = pSurfList->current()->handle();
 
2847
            pOUCmd->u.in.flags = VBOXVHWA_OVER_HIDE;
 
2848
 
 
2849
            pCmdList->push_back(pCmd);
 
2850
        }
 
2851
 
 
2852
        /* 2. destroy overlay */
 
2853
        const SurfList & surfaces = pSurfList->surfaces();
 
2854
 
 
2855
        for (SurfList::const_iterator sIt = surfaces.begin();
 
2856
                sIt != surfaces.end(); ++ sIt)
 
2857
        {
 
2858
            VBoxVHWASurfaceBase *pCurSurf = (*sIt);
 
2859
            pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
 
2860
            VBOXVHWACMD_SURF_DESTROY *pSDCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
 
2861
            pSDCmd->u.in.hSurf = pCurSurf->handle();
 
2862
 
 
2863
            pCmdList->push_back(pCmd);
 
2864
        }
 
2865
    }
 
2866
 
 
2867
    /* 3. destroy primaries */
 
2868
    const SurfList & surfaces = mDisplay.primaries().surfaces();
 
2869
    for (SurfList::const_iterator sIt = surfaces.begin();
 
2870
            sIt != surfaces.end(); ++ sIt)
 
2871
    {
 
2872
        VBoxVHWASurfaceBase *pCurSurf = (*sIt);
 
2873
        if(pCurSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID)
 
2874
        {
 
2875
            pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
 
2876
            VBOXVHWACMD_SURF_DESTROY *pSDCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
 
2877
            pSDCmd->u.in.hSurf = pCurSurf->handle();
 
2878
 
 
2879
            pCmdList->push_back(pCmd);
 
2880
        }
 
2881
    }
 
2882
 
 
2883
    return VINF_SUCCESS;
 
2884
}
 
2885
 
 
2886
#ifdef VBOX_WITH_VIDEOHWACCEL
 
2887
void VBoxGLWidget::vboxDoVHWACmd(void *cmd)
 
2888
{
 
2889
    vboxDoVHWACmdExec(cmd);
 
2890
 
 
2891
    CDisplay display = mView->console().GetDisplay();
 
2892
    Assert (!display.isNull());
 
2893
 
 
2894
    display.CompleteVHWACommand((BYTE*)cmd);
 
2895
}
 
2896
 
 
2897
void VBoxGLWidget::vboxDoVHWACmdAndFree(void *cmd)
 
2898
{
 
2899
    vboxDoVHWACmdExec(cmd);
 
2900
 
 
2901
    free(cmd);
 
2902
}
 
2903
 
 
2904
void VBoxGLWidget::vboxDoVHWACmdExec(void *cmd)
 
2905
{
 
2906
    struct _VBOXVHWACMD * pCmd = (struct _VBOXVHWACMD *)cmd;
 
2907
    switch(pCmd->enmCmd)
 
2908
    {
 
2909
        case VBOXVHWACMD_TYPE_SURF_CANCREATE:
 
2910
        {
 
2911
            VBOXVHWACMD_SURF_CANCREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CANCREATE);
 
2912
            pCmd->rc = vhwaSurfaceCanCreate(pBody);
 
2913
        } break;
 
2914
        case VBOXVHWACMD_TYPE_SURF_CREATE:
 
2915
        {
 
2916
            VBOXVHWACMD_SURF_CREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
 
2917
            pCmd->rc = vhwaSurfaceCreate(pBody);
 
2918
        } break;
 
2919
        case VBOXVHWACMD_TYPE_SURF_DESTROY:
 
2920
        {
 
2921
            VBOXVHWACMD_SURF_DESTROY * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
 
2922
            pCmd->rc = vhwaSurfaceDestroy(pBody);
 
2923
        } break;
 
2924
        case VBOXVHWACMD_TYPE_SURF_LOCK:
 
2925
        {
 
2926
            VBOXVHWACMD_SURF_LOCK * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
 
2927
            pCmd->rc = vhwaSurfaceLock(pBody);
 
2928
        } break;
 
2929
        case VBOXVHWACMD_TYPE_SURF_UNLOCK:
 
2930
        {
 
2931
            VBOXVHWACMD_SURF_UNLOCK * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_UNLOCK);
 
2932
            pCmd->rc = vhwaSurfaceUnlock(pBody);
 
2933
        } break;
 
2934
        case VBOXVHWACMD_TYPE_SURF_BLT:
 
2935
        {
 
2936
            VBOXVHWACMD_SURF_BLT * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
 
2937
            pCmd->rc = vhwaSurfaceBlt(pBody);
 
2938
        } break;
 
2939
        case VBOXVHWACMD_TYPE_SURF_FLIP:
 
2940
        {
 
2941
            VBOXVHWACMD_SURF_FLIP * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
 
2942
            pCmd->rc = vhwaSurfaceFlip(pBody);
 
2943
        } break;
 
2944
        case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
 
2945
        {
 
2946
            VBOXVHWACMD_SURF_OVERLAY_UPDATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
 
2947
            pCmd->rc = vhwaSurfaceOverlayUpdate(pBody);
 
2948
        } break;
 
2949
        case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
 
2950
        {
 
2951
            VBOXVHWACMD_SURF_OVERLAY_SETPOSITION * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_SETPOSITION);
 
2952
            pCmd->rc = vhwaSurfaceOverlaySetPosition(pBody);
 
2953
        } break;
 
2954
        case VBOXVHWACMD_TYPE_SURF_COLORKEY_SET:
 
2955
        {
 
2956
            VBOXVHWACMD_SURF_COLORKEY_SET * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORKEY_SET);
 
2957
            pCmd->rc = vhwaSurfaceColorkeySet(pBody);
 
2958
        } break;
 
2959
        case VBOXVHWACMD_TYPE_QUERY_INFO1:
 
2960
        {
 
2961
            VBOXVHWACMD_QUERYINFO1 * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
 
2962
            pCmd->rc = vhwaQueryInfo1(pBody);
 
2963
        } break;
 
2964
        case VBOXVHWACMD_TYPE_QUERY_INFO2:
 
2965
        {
 
2966
            VBOXVHWACMD_QUERYINFO2 * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
 
2967
            pCmd->rc = vhwaQueryInfo2(pBody);
 
2968
        } break;
 
2969
        case VBOXVHWACMD_TYPE_ENABLE:
 
2970
        case VBOXVHWACMD_TYPE_DISABLE:
 
2971
            pCmd->rc = VINF_SUCCESS;
 
2972
            break;
 
2973
        case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
 
2974
        {
 
2975
            VBOXVHWACMD_HH_CONSTRUCT * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
 
2976
            pCmd->rc = vhwaConstruct(pBody);
 
2977
        } break;
 
2978
        default:
 
2979
            Assert(0);
 
2980
            pCmd->rc = VERR_NOT_IMPLEMENTED;
 
2981
            break;
 
2982
    }
 
2983
}
 
2984
 
 
2985
int VBoxGLWidget::vhwaSurfaceCanCreate(struct _VBOXVHWACMD_SURF_CANCREATE *pCmd)
 
2986
{
 
2987
    VBOXQGLLOG_ENTER(("\n"));
 
2988
 
 
2989
    const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(context());
 
2990
 
 
2991
    if(!(pCmd->SurfInfo.flags & VBOXVHWA_SD_CAPS))
 
2992
    {
 
2993
        Assert(0);
 
2994
        pCmd->u.out.ErrInfo = -1;
 
2995
        return VINF_SUCCESS;
 
2996
    }
 
2997
#ifdef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
 
2998
    if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN)
 
2999
    {
 
3000
#ifdef DEBUGVHWASTRICT
 
3001
        Assert(0);
 
3002
#endif
 
3003
        pCmd->u.out.ErrInfo = -1;
 
3004
        return VINF_SUCCESS;
 
3005
    }
 
3006
#endif
 
3007
 
 
3008
    if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
 
3009
    {
 
3010
        if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_COMPLEX)
 
3011
        {
 
3012
#ifdef DEBUG_misha
 
3013
            Assert(0);
 
3014
#endif
 
3015
            pCmd->u.out.ErrInfo = -1;
 
3016
        }
 
3017
        else
 
3018
        {
 
3019
            pCmd->u.out.ErrInfo = 0;
 
3020
        }
 
3021
        return VINF_SUCCESS;
 
3022
    }
 
3023
 
 
3024
#ifdef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
 
3025
    if((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) == 0)
 
3026
    {
 
3027
#ifdef DEBUGVHWASTRICT
 
3028
        Assert(0);
 
3029
#endif
 
3030
        pCmd->u.out.ErrInfo = -1;
 
3031
        return VINF_SUCCESS;
 
3032
    }
 
3033
#endif
 
3034
 
 
3035
    if(pCmd->u.in.bIsDifferentPixelFormat)
 
3036
    {
 
3037
        if(!(pCmd->SurfInfo.flags & VBOXVHWA_SD_PIXELFORMAT))
 
3038
        {
 
3039
            Assert(0);
 
3040
            pCmd->u.out.ErrInfo = -1;
 
3041
            return VINF_SUCCESS;
 
3042
        }
 
3043
 
 
3044
        if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
 
3045
        {
 
3046
            if(pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 32
 
3047
                    || pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 24)
 
3048
            {
 
3049
                Assert(0);
 
3050
                pCmd->u.out.ErrInfo = -1;
 
3051
                return VINF_SUCCESS;
 
3052
            }
 
3053
        }
 
3054
        else if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
 
3055
        {
 
3056
            /* detect whether we support this format */
 
3057
            bool bFound = false;
 
3058
            for(int i = 0; i < info.getFourccSupportedCount(); i++)
 
3059
            {
 
3060
                if(info.getFourccSupportedList()[i] == pCmd->SurfInfo.PixelFormat.fourCC)
 
3061
                {
 
3062
                    bFound = true;
 
3063
                    break;
 
3064
                }
 
3065
            }
 
3066
 
 
3067
            if(!bFound)
 
3068
            {
 
3069
                VBOXQGLLOG(("!!unsupported fourcc!!!: %c%c%c%c\n",
 
3070
                        (pCmd->SurfInfo.PixelFormat.fourCC & 0x000000ff),
 
3071
                                (pCmd->SurfInfo.PixelFormat.fourCC & 0x0000ff00) >> 8,
 
3072
                                (pCmd->SurfInfo.PixelFormat.fourCC & 0x00ff0000) >> 16,
 
3073
                        (pCmd->SurfInfo.PixelFormat.fourCC & 0xff000000) >> 24
 
3074
                        ));
 
3075
//#ifdef DEBUG_misha
 
3076
//                Assert(0);
 
3077
//#endif
 
3078
                pCmd->u.out.ErrInfo = -1;
 
3079
                return VINF_SUCCESS;
 
3080
            }
 
3081
        }
 
3082
        else
 
3083
        {
 
3084
            Assert(0);
 
3085
            pCmd->u.out.ErrInfo = -1;
 
3086
            return VINF_SUCCESS;
 
3087
        }
 
3088
    }
 
3089
 
 
3090
    pCmd->u.out.ErrInfo = 0;
 
3091
    return VINF_SUCCESS;
 
3092
}
 
3093
 
 
3094
int VBoxGLWidget::vhwaSurfaceCreate(struct _VBOXVHWACMD_SURF_CREATE *pCmd)
 
3095
{
 
3096
    VBOXQGLLOG_ENTER(("\n"));
 
3097
 
 
3098
    uint32_t handle = VBOXVHWA_SURFHANDLE_INVALID;
 
3099
    if(pCmd->SurfInfo.hSurf != VBOXVHWA_SURFHANDLE_INVALID)
 
3100
    {
 
3101
        handle = pCmd->SurfInfo.hSurf;
 
3102
        if(mSurfHandleTable.get(handle))
 
3103
        {
 
3104
//            do
 
3105
//            {
 
3106
//                if(!mcVGASurfCreated)
 
3107
//                {
 
3108
//                    /* check if it is a primary surface that needs handle adjusting*/
 
3109
//                    if((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
 
3110
//                            && handle2Surface(handle) == mDisplay.getVGA())
 
3111
//                    {
 
3112
//                        /* remove, the primary surface will be assigned to a new handle assumed by the guest */
 
3113
//                        mSurfHandleTable.remove(handle);
 
3114
//                        break;
 
3115
//                    }
 
3116
//                }
 
3117
                Assert(0);
 
3118
                return VERR_GENERAL_FAILURE;
 
3119
//            }while(0);
 
3120
        }
 
3121
    }
 
3122
 
 
3123
    VBoxVHWASurfaceBase *surf = NULL;
 
3124
//    VBoxVHWAColorFormat *pFormat = NULL, Format;
 
3125
    bool bNoPBO = false;
 
3126
    bool bPrimary = false;
 
3127
 
 
3128
    VBoxVHWAColorKey *pDstBltCKey = NULL, DstBltCKey;
 
3129
    VBoxVHWAColorKey *pSrcBltCKey = NULL, SrcBltCKey;
 
3130
    VBoxVHWAColorKey *pDstOverlayCKey = NULL, DstOverlayCKey;
 
3131
    VBoxVHWAColorKey *pSrcOverlayCKey = NULL, SrcOverlayCKey;
 
3132
    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
 
3133
    {
 
3134
        DstBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstBltCK.high, pCmd->SurfInfo.DstBltCK.low);
 
3135
        pDstBltCKey = &DstBltCKey;
 
3136
    }
 
3137
    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
 
3138
    {
 
3139
        SrcBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcBltCK.high, pCmd->SurfInfo.SrcBltCK.low);
 
3140
        pSrcBltCKey = &SrcBltCKey;
 
3141
    }
 
3142
    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
 
3143
    {
 
3144
        DstOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstOverlayCK.high, pCmd->SurfInfo.DstOverlayCK.low);
 
3145
        pDstOverlayCKey = &DstOverlayCKey;
 
3146
    }
 
3147
    if(pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
 
3148
    {
 
3149
        SrcOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcOverlayCK.high, pCmd->SurfInfo.SrcOverlayCK.low);
 
3150
        pSrcOverlayCKey = &SrcOverlayCKey;
 
3151
    }
 
3152
 
 
3153
    if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
 
3154
    {
 
3155
        bNoPBO = true;
 
3156
        bPrimary = true;
 
3157
        VBoxVHWASurfaceBase * pVga = vboxGetVGASurface();
 
3158
 
 
3159
        Assert((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN) == 0);
 
3160
        if(pVga->handle() == VBOXVHWA_SURFHANDLE_INVALID
 
3161
                && (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN) == 0)
 
3162
        {
 
3163
            Assert(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB);
 
3164
//            if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
 
3165
            {
 
3166
                Assert(pCmd->SurfInfo.width == pVga->width());
 
3167
                Assert(pCmd->SurfInfo.height == pVga->height());
 
3168
//                if(pCmd->SurfInfo.width == pVga->width()
 
3169
//                        && pCmd->SurfInfo.height == pVga->height())
 
3170
                {
 
3171
                    VBoxVHWAColorFormat format(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
 
3172
                                                pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
 
3173
                                                pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
 
3174
                                                pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
 
3175
                    Assert(pVga->colorFormat().equals(format));
 
3176
//                    if(pVga->colorFormat().equals(format))
 
3177
                    {
 
3178
                        surf = pVga;
 
3179
 
 
3180
                        surf->setDstBltCKey(pDstBltCKey);
 
3181
                        surf->setSrcBltCKey(pSrcBltCKey);
 
3182
 
 
3183
                        surf->setDefaultDstOverlayCKey(pDstOverlayCKey);
 
3184
                        surf->resetDefaultDstOverlayCKey();
 
3185
 
 
3186
                        surf->setDefaultSrcOverlayCKey(pDstOverlayCKey);
 
3187
                        surf->resetDefaultSrcOverlayCKey();
 
3188
//                        mbVGASurfCreated = true;
 
3189
                    }
 
3190
                }
 
3191
            }
 
3192
        }
 
3193
    }
 
3194
    else if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN)
 
3195
    {
 
3196
        bNoPBO = true;
 
3197
    }
 
3198
 
 
3199
    if(!surf)
 
3200
    {
 
3201
        if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
 
3202
        {
 
3203
            VBoxVHWAColorFormat format(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
 
3204
                                            pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
 
3205
                                            pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
 
3206
                                            pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
 
3207
            QSize surfSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height);
 
3208
            QRect primaryRect = mDisplay.getPrimary()->rect();
 
3209
            surf = new VBoxVHWASurfaceBase(this, surfSize,
 
3210
//                        ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) ? mDisplay.getPrimary()->rect().size() : &surfSize),
 
3211
                        primaryRect,
 
3212
                        QRect(0, 0, surfSize.width(), surfSize.height()),
 
3213
                        mViewport,
 
3214
                        format,
 
3215
                        pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey,
 
3216
#ifdef VBOXVHWA_USE_TEXGROUP
 
3217
                        0,
 
3218
#endif
 
3219
                        bNoPBO);
 
3220
        }
 
3221
        else if(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
 
3222
        {
 
3223
            QSize surfSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height);
 
3224
            QRect primaryRect = mDisplay.getPrimary()->rect();
 
3225
 
 
3226
            VBoxVHWAColorFormat format(pCmd->SurfInfo.PixelFormat.fourCC);
 
3227
            surf = new VBoxVHWASurfaceBase(this, surfSize,
 
3228
            //                        ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) ? mDisplay.getPrimary()->rect().size() : &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height)),
 
3229
                                    primaryRect,
 
3230
                                    QRect(0, 0, surfSize.width(), surfSize.height()),
 
3231
                                    mViewport,
 
3232
                                    format,
 
3233
                                    pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey,
 
3234
#ifdef VBOXVHWA_USE_TEXGROUP
 
3235
                                    0,
 
3236
#endif
 
3237
                                    bNoPBO);
 
3238
        }
 
3239
        else
 
3240
        {
 
3241
            Assert(0);
 
3242
            VBOXQGLLOG_EXIT(("pSurf (0x%x)\n",surf));
 
3243
            return VERR_GENERAL_FAILURE;
 
3244
        }
 
3245
 
 
3246
        uchar * addr = vboxVRAMAddressFromOffset(pCmd->SurfInfo.offSurface);
 
3247
        surf->init(mDisplay.getPrimary(), addr);
 
3248
 
 
3249
        if(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY)
 
3250
        {
 
3251
#ifdef DEBUG_misha
 
3252
            Assert(!bNoPBO);
 
3253
#endif
 
3254
 
 
3255
            if(!mConstructingList)
 
3256
            {
 
3257
                mConstructingList = new VBoxVHWASurfList();
 
3258
                mcRemaining2Contruct = pCmd->SurfInfo.cBackBuffers+1;
 
3259
                mDisplay.addOverlay(mConstructingList);
 
3260
            }
 
3261
 
 
3262
            mConstructingList->add(surf);
 
3263
            mcRemaining2Contruct--;
 
3264
            if(!mcRemaining2Contruct)
 
3265
            {
 
3266
                mConstructingList = NULL;
 
3267
            }
 
3268
        }
 
3269
        else
 
3270
        {
 
3271
            VBoxVHWASurfaceBase * pVga = vboxGetVGASurface();
 
3272
            Assert(pVga->handle() != VBOXVHWA_SURFHANDLE_INVALID);
 
3273
            Assert(pVga != surf); NOREF(pVga);
 
3274
//            Assert(mbVGASurfCreated);
 
3275
            mDisplay.getVGA()->getComplexList()->add(surf);
 
3276
#ifdef DEBUGVHWASTRICT
 
3277
            Assert(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_VISIBLE);
 
3278
#endif
 
3279
            if(bPrimary)
 
3280
            {
 
3281
                Assert(surf->getComplexList() == mDisplay.getVGA()->getComplexList());
 
3282
                surf->getComplexList()->setCurrentVisible(surf);
 
3283
                mDisplay.updateVGA(surf);
 
3284
            }
 
3285
        }
 
3286
    }
 
3287
 
 
3288
    Assert(mDisplay.getVGA() == mDisplay.getPrimary());
 
3289
 
 
3290
    /* tell the guest how we think the memory is organized */
 
3291
    VBOXQGLLOG(("bps: %d\n", surf->bitsPerPixel()));
 
3292
 
 
3293
    pCmd->SurfInfo.pitch        = surf->bitsPerPixel() * surf->width() / 8;
 
3294
    pCmd->SurfInfo.sizeX = surf->memSize();
 
3295
    pCmd->SurfInfo.sizeY = 1;
 
3296
 
 
3297
    if(handle != VBOXVHWA_SURFHANDLE_INVALID)
 
3298
    {
 
3299
        bool bSuccess = mSurfHandleTable.mapPut(handle, surf);
 
3300
        Assert(bSuccess);
 
3301
        if(!bSuccess)
 
3302
        {
 
3303
            /* @todo: this is very bad, should not be here */
 
3304
            return VERR_GENERAL_FAILURE;
 
3305
        }
 
3306
    }
 
3307
    else
 
3308
    {
 
3309
        /* tell the guest our handle */
 
3310
        handle = mSurfHandleTable.put(surf);
 
3311
        pCmd->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)handle;
 
3312
    }
 
3313
 
 
3314
    Assert(handle != VBOXVHWA_SURFHANDLE_INVALID);
 
3315
    Assert(surf->handle() == VBOXVHWA_SURFHANDLE_INVALID);
 
3316
    surf->setHandle(handle);
 
3317
    Assert(surf->handle() == handle);
 
3318
 
 
3319
    VBOXQGLLOG_EXIT(("pSurf (0x%x)\n",surf));
 
3320
 
 
3321
    return VINF_SUCCESS;
 
3322
}
 
3323
 
 
3324
int VBoxGLWidget::vhwaSurfaceDestroy(struct _VBOXVHWACMD_SURF_DESTROY *pCmd)
 
3325
{
 
3326
    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
 
3327
    VBoxVHWASurfList *pList = pSurf->getComplexList();
 
3328
    Assert(pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID);
 
3329
 
 
3330
    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
 
3331
    if(pList != mDisplay.getVGA()->getComplexList())
 
3332
    {
 
3333
        Assert(pList);
 
3334
        pList->remove(pSurf);
 
3335
        if(pList->surfaces().empty())
 
3336
        {
 
3337
            mDisplay.removeOverlay(pList);
 
3338
//                Assert(mConstructingList != pList);
 
3339
            if(pList == mConstructingList)
 
3340
            {
 
3341
                mConstructingList = NULL;
 
3342
                mcRemaining2Contruct = 0;
 
3343
            }
 
3344
            delete pList;
 
3345
        }
 
3346
 
 
3347
        delete(pSurf);
 
3348
    }
 
3349
    else
 
3350
    {
 
3351
        Assert(pList->size() >= 1);
 
3352
        if(pList->size() > 1)
 
3353
        {
 
3354
            if(pSurf == mDisplay.getVGA())
 
3355
            {
 
3356
                const SurfList & surfaces = pList->surfaces();
 
3357
 
 
3358
                for (SurfList::const_iterator it = surfaces.begin();
 
3359
                         it != surfaces.end(); ++ it)
 
3360
                {
 
3361
                    VBoxVHWASurfaceBase *pCurSurf = (*it);
 
3362
                    if(pCurSurf != pSurf)
 
3363
                    {
 
3364
                        mDisplay.updateVGA(pCurSurf);
 
3365
                        pList->setCurrentVisible(pCurSurf);
 
3366
                        break;
 
3367
                    }
 
3368
                }
 
3369
            }
 
3370
 
 
3371
            pList->remove(pSurf);
 
3372
            delete(pSurf);
 
3373
        }
 
3374
        else
 
3375
        {
 
3376
            pSurf->setHandle(VBOXVHWA_SURFHANDLE_INVALID);
 
3377
        }
 
3378
    }
 
3379
 
 
3380
    /* just in case we destroy a visible overlay sorface */
 
3381
    mRepaintNeeded = true;
 
3382
 
 
3383
    void * test = mSurfHandleTable.remove(pCmd->u.in.hSurf);
 
3384
    Assert(test); NOREF(test);
 
3385
 
 
3386
    return VINF_SUCCESS;
 
3387
}
 
3388
 
 
3389
#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_RB(_pr) \
 
3390
             QRect((_pr)->left,                     \
 
3391
                 (_pr)->top,                        \
 
3392
                 (_pr)->right - (_pr)->left + 1,    \
 
3393
                 (_pr)->bottom - (_pr)->top + 1)
 
3394
 
 
3395
#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(_pr) \
 
3396
             QRect((_pr)->left,                     \
 
3397
                 (_pr)->top,                        \
 
3398
                 (_pr)->right - (_pr)->left,        \
 
3399
                 (_pr)->bottom - (_pr)->top)
 
3400
 
 
3401
int VBoxGLWidget::vhwaSurfaceLock(struct _VBOXVHWACMD_SURF_LOCK *pCmd)
 
3402
{
 
3403
    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
 
3404
    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
 
3405
    vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
 
3406
    if(pCmd->u.in.rectValid)
 
3407
    {
 
3408
        QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.rect);
 
3409
        return pSurf->lock(&r, pCmd->u.in.flags);
 
3410
    }
 
3411
    return pSurf->lock(NULL, pCmd->u.in.flags);
 
3412
}
 
3413
 
 
3414
int VBoxGLWidget::vhwaSurfaceUnlock(struct _VBOXVHWACMD_SURF_UNLOCK *pCmd)
 
3415
{
 
3416
    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
 
3417
#ifdef DEBUG_misha
 
3418
    /* for performance reasons we should receive unlock for visible surfaces only
 
3419
     * other surfaces receive unlock only once becoming visible, e.g. on DdFlip
 
3420
     * Ensure this is so*/
 
3421
    if(pSurf != mDisplay.getPrimary())
 
3422
    {
 
3423
        const OverlayList & overlays = mDisplay.overlays();
 
3424
        bool bFound = false;
 
3425
 
 
3426
        if(!mDisplay.isPrimary(pSurf))
 
3427
        {
 
3428
            for (OverlayList::const_iterator it = overlays.begin();
 
3429
                 it != overlays.end(); ++ it)
 
3430
            {
 
3431
                VBoxVHWASurfList * pSurfList = *it;
 
3432
                if(pSurfList->current() == pSurf)
 
3433
                {
 
3434
                    bFound = true;
 
3435
                    break;
 
3436
                }
 
3437
            }
 
3438
 
 
3439
            Assert(bFound);
 
3440
        }
 
3441
 
 
3442
//        Assert(bFound);
 
3443
    }
 
3444
#endif
 
3445
    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
 
3446
    if(pCmd->u.in.xUpdatedMemValid)
 
3447
    {
 
3448
        QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedMemRect);
 
3449
        pSurf->updatedMem(&r);
 
3450
    }
 
3451
 
 
3452
    return pSurf->unlock();
 
3453
}
 
3454
 
 
3455
int VBoxGLWidget::vhwaSurfaceBlt(struct _VBOXVHWACMD_SURF_BLT *pCmd)
 
3456
{
 
3457
    Q_UNUSED(pCmd);
 
3458
    return VERR_NOT_IMPLEMENTED;
 
3459
}
 
3460
 
 
3461
int VBoxGLWidget::vhwaSurfaceFlip(struct _VBOXVHWACMD_SURF_FLIP *pCmd)
 
3462
{
 
3463
    VBoxVHWASurfaceBase *pTargSurf = handle2Surface(pCmd->u.in.hTargSurf);
 
3464
    VBoxVHWASurfaceBase *pCurrSurf = handle2Surface(pCmd->u.in.hCurrSurf);
 
3465
    VBOXQGLLOG_ENTER(("pTargSurf (0x%x), pCurrSurf (0x%x)\n",pTargSurf,pCurrSurf));
 
3466
    vboxCheckUpdateAddress (pCurrSurf, pCmd->u.in.offCurrSurface);
 
3467
    vboxCheckUpdateAddress (pTargSurf, pCmd->u.in.offTargSurface);
 
3468
 
 
3469
 
 
3470
    if(pCmd->u.in.xUpdatedTargMemValid)
 
3471
    {
 
3472
        QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedTargMemRect);
 
3473
        pTargSurf->updatedMem(&r);
 
3474
    }
 
3475
    pTargSurf->getComplexList()->setCurrentVisible(pTargSurf);
 
3476
 
 
3477
    mRepaintNeeded = true;
 
3478
#ifdef DEBUG
 
3479
    pCurrSurf->cFlipsCurr++;
 
3480
    pTargSurf->cFlipsTarg++;
 
3481
#endif
 
3482
 
 
3483
    return VINF_SUCCESS;
 
3484
}
 
3485
 
 
3486
void VBoxGLWidget::vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf, struct _VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmd)
 
3487
{
 
3488
    /* get old values first to check whether we need to re-init display and program values */
 
3489
    bool bHadSrcCKey = false, bHadDstCKey = false;
 
3490
 
 
3491
    if(pDstSurf)
 
3492
    {
 
3493
        bHadSrcCKey = !!(pSrcSurf->getActiveSrcOverlayCKey());
 
3494
        bHadDstCKey = !!(pSrcSurf->getActiveDstOverlayCKey(pDstSurf));
 
3495
    }
 
3496
 
 
3497
    if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYDEST)
 
3498
    {
 
3499
        VBOXQGLLOG((", KEYDEST"));
 
3500
        /* we use src (overlay) surface to maintain overridden dst ckey info
 
3501
         * to allow multiple overlays have different overridden dst keys for one primary surface */
 
3502
        /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
 
3503
         * dst ckey value in defaultDstOverlayCKey
 
3504
         * this allows the NULL to be a valid overridden value as well
 
3505
         *  i.e.
 
3506
         * 1. indicate the value is NUL overridden, just set NULL*/
 
3507
        pSrcSurf->setOverriddenDstOverlayCKey(NULL);
 
3508
    }
 
3509
    else if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
 
3510
    {
 
3511
        VBOXQGLLOG((", KEYDESTOVERRIDE"));
 
3512
        /* we use src (overlay) surface to maintain overridden dst ckey info
 
3513
         * to allow multiple overlays have different overridden dst keys for one primary surface */
 
3514
        /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
 
3515
         * dst ckey value in defaultDstOverlayCKey
 
3516
         * this allows the NULL to be a valid overridden value as well
 
3517
         *  i.e.
 
3518
         * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
 
3519
        VBoxVHWAColorKey ckey(pCmd->u.in.desc.DstCK.high, pCmd->u.in.desc.DstCK.low);
 
3520
        VBOXQGLLOG_CKEY(" ckey: ",&ckey, "\n");
 
3521
        pSrcSurf->setOverriddenDstOverlayCKey(&ckey);
 
3522
        /* tell the ckey is enabled */
 
3523
        pSrcSurf->setDefaultDstOverlayCKey(&ckey);
 
3524
    }
 
3525
    else
 
3526
    {
 
3527
        VBOXQGLLOG((", no KEYDEST"));
 
3528
        /* we use src (overlay) surface to maintain overridden dst ckey info
 
3529
         * to allow multiple overlays have different overridden dst keys for one primary surface */
 
3530
        /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
 
3531
         * dst ckey value in defaultDstOverlayCKey
 
3532
         * this allows the NULL to be a valid overridden value as well
 
3533
         * i.e.
 
3534
         * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
 
3535
        VBoxVHWAColorKey dummyCKey(0, 0);
 
3536
        pSrcSurf->setOverriddenDstOverlayCKey(&dummyCKey);
 
3537
        /* tell the ckey is disabled */
 
3538
        pSrcSurf->setDefaultDstOverlayCKey(NULL);
 
3539
    }
 
3540
 
 
3541
    if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRC)
 
3542
    {
 
3543
        VBOXQGLLOG((", KEYSRC"));
 
3544
        pSrcSurf->resetDefaultSrcOverlayCKey();
 
3545
    }
 
3546
    else if(pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
 
3547
    {
 
3548
        VBOXQGLLOG((", KEYSRCOVERRIDE"));
 
3549
        VBoxVHWAColorKey ckey(pCmd->u.in.desc.SrcCK.high, pCmd->u.in.desc.SrcCK.low);
 
3550
        pSrcSurf->setOverriddenSrcOverlayCKey(&ckey);
 
3551
    }
 
3552
    else
 
3553
    {
 
3554
        VBOXQGLLOG((", no KEYSRC"));
 
3555
        pSrcSurf->setOverriddenSrcOverlayCKey(NULL);
 
3556
    }
 
3557
    VBOXQGLLOG(("\n"));
 
3558
    if(pDstSurf)
 
3559
    {
 
3560
        QRect dstRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.dstRect);
 
3561
        QRect srcRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.srcRect);
 
3562
 
 
3563
        VBOXQGLLOG(("*******overlay update*******\n"));
 
3564
        VBOXQGLLOG(("dstSurfSize: w(%d), h(%d)\n", pDstSurf->width(), pDstSurf->height()));
 
3565
        VBOXQGLLOG(("srcSurfSize: w(%d), h(%d)\n", pSrcSurf->width(), pSrcSurf->height()));
 
3566
        VBOXQGLLOG_QRECT("dstRect:", &dstRect, "\n");
 
3567
        VBOXQGLLOG_QRECT("srcRect:", &srcRect, "\n");
 
3568
 
 
3569
        const VBoxVHWAColorKey *pResSrcCKey = pSrcSurf->getActiveSrcOverlayCKey();
 
3570
        const VBoxVHWAColorKey *pResDstCKey = pSrcSurf->getActiveDstOverlayCKey(pDstSurf);
 
3571
 
 
3572
        if(bHadSrcCKey != !!pResSrcCKey || bHadDstCKey != !!pResDstCKey)
 
3573
        {
 
3574
            pSrcSurf->setVisibilityReinitFlag();
 
3575
        }
 
3576
        else if(pResSrcCKey || pResDstCKey)
 
3577
        {
 
3578
            VBoxVHWAGlProgramVHWA *pProgram = pSrcSurf->getProgram(pDstSurf);
 
3579
            if(pProgram)
 
3580
            {
 
3581
                pProgram->start();
 
3582
                if(pResSrcCKey)
 
3583
                {
 
3584
                    VBoxVHWASurfaceBase::setCKey(pProgram, &pSrcSurf->colorFormat(), pResSrcCKey, false);
 
3585
                }
 
3586
                if(pResDstCKey)
 
3587
                {
 
3588
                    VBoxVHWASurfaceBase::setCKey(pProgram, &pDstSurf->colorFormat(), pResDstCKey, true);
 
3589
                }
 
3590
                pProgram->stop();
 
3591
            }
 
3592
        }
 
3593
 
 
3594
        pSrcSurf->setRects(dstRect, srcRect);
 
3595
 
 
3596
    }
 
3597
}
 
3598
 
 
3599
int VBoxGLWidget::vhwaSurfaceOverlayUpdate(struct _VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmd)
 
3600
{
 
3601
    VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
 
3602
    VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
 
3603
    vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
 
3604
    VBOXQGLLOG(("OverlayUpdate: pSrcSurf (0x%x)\n",pSrcSurf));
 
3605
    VBoxVHWASurfaceBase *pDstSurf = NULL;
 
3606
 
 
3607
    if(pCmd->u.in.hDstSurf)
 
3608
    {
 
3609
        pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
 
3610
        vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
 
3611
        VBOXQGLLOG(("pDstSurf (0x%x)\n",pDstSurf));
 
3612
#ifdef DEBUGVHWASTRICT
 
3613
        Assert(pDstSurf == mDisplay.getVGA());
 
3614
        Assert(mDisplay.getVGA() == mDisplay.getPrimary());
 
3615
#endif
 
3616
        Assert(pDstSurf->getComplexList() == mDisplay.getVGA()->getComplexList());
 
3617
 
 
3618
        if(pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
 
3619
        {
 
3620
            if(pDstSurf != mDisplay.getPrimary())
 
3621
            {
 
3622
                mDisplay.updateVGA(pDstSurf);
 
3623
                pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
 
3624
            }
 
3625
        }
 
3626
    }
 
3627
 
 
3628
    const SurfList & surfaces = pList->surfaces();
 
3629
 
 
3630
    for (SurfList::const_iterator it = surfaces.begin();
 
3631
             it != surfaces.end(); ++ it)
 
3632
    {
 
3633
        VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
 
3634
        vhwaDoSurfaceOverlayUpdate(pDstSurf, pCurSrcSurf, pCmd);
 
3635
    }
 
3636
 
 
3637
    if(pCmd->u.in.flags & VBOXVHWA_OVER_HIDE)
 
3638
    {
 
3639
        VBOXQGLLOG(("hide\n"));
 
3640
        pList->setCurrentVisible(NULL);
 
3641
    }
 
3642
    else if(pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
 
3643
    {
 
3644
        VBOXQGLLOG(("show\n"));
 
3645
        pList->setCurrentVisible(pSrcSurf);
 
3646
    }
 
3647
 
 
3648
    mRepaintNeeded = true;
 
3649
 
 
3650
    return VINF_SUCCESS;
 
3651
}
 
3652
 
 
3653
int VBoxGLWidget::vhwaSurfaceOverlaySetPosition(struct _VBOXVHWACMD_SURF_OVERLAY_SETPOSITION *pCmd)
 
3654
{
 
3655
    VBoxVHWASurfaceBase *pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
 
3656
    VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
 
3657
 
 
3658
    VBOXQGLLOG_ENTER(("pDstSurf (0x%x), pSrcSurf (0x%x)\n",pDstSurf,pSrcSurf));
 
3659
 
 
3660
    vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
 
3661
    vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
 
3662
 
 
3663
    VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
 
3664
    const SurfList & surfaces = pList->surfaces();
 
3665
 
 
3666
    QPoint pos(pCmd->u.in.xPos, pCmd->u.in.yPos);
 
3667
 
 
3668
#ifdef DEBUGVHWASTRICT
 
3669
    Assert(pDstSurf == mDisplay.getVGA());
 
3670
    Assert(mDisplay.getVGA() == mDisplay.getPrimary());
 
3671
#endif
 
3672
    if(pSrcSurf->getComplexList()->current() != NULL)
 
3673
    {
 
3674
        Assert(pDstSurf);
 
3675
        if(pDstSurf != mDisplay.getPrimary())
 
3676
        {
 
3677
            mDisplay.updateVGA(pDstSurf);
 
3678
            pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
 
3679
        }
 
3680
    }
 
3681
 
 
3682
    mRepaintNeeded = true;
 
3683
 
 
3684
    for (SurfList::const_iterator it = surfaces.begin();
 
3685
             it != surfaces.end(); ++ it)
 
3686
    {
 
3687
        VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
 
3688
        pCurSrcSurf->setTargRectPosition(pos);
 
3689
    }
 
3690
 
 
3691
    return VINF_SUCCESS;
 
3692
}
 
3693
 
 
3694
int VBoxGLWidget::vhwaSurfaceColorkeySet(struct _VBOXVHWACMD_SURF_COLORKEY_SET *pCmd)
 
3695
{
 
3696
    VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
 
3697
 
 
3698
    VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
 
3699
 
 
3700
    vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
 
3701
 
 
3702
    mRepaintNeeded = true;
 
3703
 
 
3704
//    VBOXVHWA_CKEY_COLORSPACE
 
3705
    if(pCmd->u.in.flags & VBOXVHWA_CKEY_DESTBLT)
 
3706
    {
 
3707
        VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
 
3708
        pSurf->setDstBltCKey(&ckey);
 
3709
    }
 
3710
    if(pCmd->u.in.flags & VBOXVHWA_CKEY_DESTOVERLAY)
 
3711
    {
 
3712
        VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
 
3713
        pSurf->setDefaultDstOverlayCKey(&ckey);
 
3714
    }
 
3715
    if(pCmd->u.in.flags & VBOXVHWA_CKEY_SRCBLT)
 
3716
    {
 
3717
        VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
 
3718
        pSurf->setSrcBltCKey(&ckey);
 
3719
    }
 
3720
    if(pCmd->u.in.flags & VBOXVHWA_CKEY_SRCOVERLAY)
 
3721
    {
 
3722
        VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
 
3723
        pSurf->setDefaultSrcOverlayCKey(&ckey);
 
3724
    }
 
3725
 
 
3726
    /* ensure all overlays programs & display lists are updated */
 
3727
    const OverlayList & overlays = mDisplay.overlays();
 
3728
    for (OverlayList::const_iterator it = overlays.begin();
 
3729
         it != overlays.end(); ++ it)
 
3730
    {
 
3731
        VBoxVHWASurfList * pSurfList = *it;
 
3732
        const SurfList & surfaces = pSurfList->surfaces();
 
3733
        for (SurfList::const_iterator sit = surfaces.begin();
 
3734
             sit != surfaces.end(); ++ sit)
 
3735
        {
 
3736
            VBoxVHWASurfaceBase *pOverlaySurf = *sit;
 
3737
            pOverlaySurf->setVisibilityReinitFlag();
 
3738
        }
 
3739
    }
 
3740
    return VINF_SUCCESS;
 
3741
}
 
3742
 
 
3743
int VBoxGLWidget::vhwaQueryInfo1(struct _VBOXVHWACMD_QUERYINFO1 *pCmd)
 
3744
{
 
3745
    VBOXQGLLOG_ENTER(("\n"));
 
3746
    bool bEnabled = false;
 
3747
    const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(context());
 
3748
    if(info.isVHWASupported())
 
3749
    {
 
3750
        Assert(pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ);
 
3751
        if(pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ)
 
3752
        {
 
3753
            Assert(pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN);
 
3754
            if(pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN)
 
3755
            {
 
3756
                Assert(pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD);
 
3757
                if(pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD)
 
3758
                {
 
3759
                    Assert(pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV);
 
3760
                    if(pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV)
 
3761
                    {
 
3762
                        bEnabled = true;
 
3763
                    }
 
3764
                }
 
3765
            }
 
3766
        }
 
3767
    }
 
3768
 
 
3769
    memset(pCmd, 0, sizeof(VBOXVHWACMD_QUERYINFO1));
 
3770
    if(bEnabled)
 
3771
    {
 
3772
        pCmd->u.out.cfgFlags = VBOXVHWA_CFG_ENABLED;
 
3773
 
 
3774
        pCmd->u.out.caps =
 
3775
//                        VBOXVHWA_CAPS_BLT | VBOXVHWA_CAPS_BLTSTRETCH | VBOXVHWA_CAPS_BLTQUEUE
 
3776
//                                 // | VBOXVHWA_CAPS_BLTCOLORFILL not supported, although adding it is trivial
 
3777
//                                 // | VBOXVHWA_CAPS_BLTFOURCC set below if shader support is available
 
3778
                                 VBOXVHWA_CAPS_OVERLAY
 
3779
                                 | VBOXVHWA_CAPS_OVERLAYSTRETCH
 
3780
                                 | VBOXVHWA_CAPS_OVERLAYCANTCLIP
 
3781
                                 // | VBOXVHWA_CAPS_OVERLAYFOURCC set below if shader support is available
 
3782
                                 ;
 
3783
 
 
3784
        pCmd->u.out.caps2 = VBOXVHWA_CAPS2_CANRENDERWINDOWED
 
3785
                                    | VBOXVHWA_CAPS2_WIDESURFACES;
 
3786
 
 
3787
        //TODO: setup stretchCaps
 
3788
        pCmd->u.out.stretchCaps = 0;
 
3789
 
 
3790
        pCmd->u.out.numOverlays = 1;
 
3791
        /* TODO: set curOverlays properly */
 
3792
        pCmd->u.out.curOverlays = 0;
 
3793
 
 
3794
        pCmd->u.out.surfaceCaps =
 
3795
                            VBOXVHWA_SCAPS_PRIMARYSURFACE
 
3796
#ifndef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
 
3797
                            | VBOXVHWA_SCAPS_OFFSCREENPLAIN
 
3798
#endif
 
3799
                            | VBOXVHWA_SCAPS_FLIP
 
3800
                            | VBOXVHWA_SCAPS_LOCALVIDMEM
 
3801
                            | VBOXVHWA_SCAPS_OVERLAY
 
3802
                    //        | VBOXVHWA_SCAPS_BACKBUFFER
 
3803
                    //        | VBOXVHWA_SCAPS_FRONTBUFFER
 
3804
                    //        | VBOXVHWA_SCAPS_VIDEOMEMORY
 
3805
                    //        | VBOXVHWA_SCAPS_COMPLEX
 
3806
                    //        | VBOXVHWA_SCAPS_VISIBLE
 
3807
                            ;
 
3808
 
 
3809
        if(info.getGlInfo().isFragmentShaderSupported() && info.getGlInfo().getMultiTexNumSupported() >= 2)
 
3810
        {
 
3811
            pCmd->u.out.caps |= VBOXVHWA_CAPS_COLORKEY
 
3812
                            | VBOXVHWA_CAPS_COLORKEYHWASSIST
 
3813
                            ;
 
3814
 
 
3815
            pCmd->u.out.colorKeyCaps =
 
3816
//                          VBOXVHWA_CKEYCAPS_DESTBLT | VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACE | VBOXVHWA_CKEYCAPS_SRCBLT| VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACE |
 
3817
//                          VBOXVHWA_CKEYCAPS_SRCOVERLAY | VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE |
 
3818
                            VBOXVHWA_CKEYCAPS_DESTOVERLAY          |
 
3819
                            VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE;
 
3820
                            ;
 
3821
 
 
3822
            if(info.getGlInfo().isTextureRectangleSupported())
 
3823
            {
 
3824
                pCmd->u.out.caps |= VBOXVHWA_CAPS_OVERLAYFOURCC
 
3825
//                              | VBOXVHWA_CAPS_BLTFOURCC
 
3826
                                ;
 
3827
 
 
3828
                pCmd->u.out.colorKeyCaps |=
 
3829
//                               VBOXVHWA_CKEYCAPS_SRCOVERLAYYUV |
 
3830
                                 VBOXVHWA_CKEYCAPS_DESTOVERLAYYUV;
 
3831
                                 ;
 
3832
 
 
3833
//              pCmd->u.out.caps2 |= VBOXVHWA_CAPS2_COPYFOURCC;
 
3834
 
 
3835
                pCmd->u.out.numFourCC = info.getFourccSupportedCount();
 
3836
            }
 
3837
        }
 
3838
    }
 
3839
 
 
3840
    return VINF_SUCCESS;
 
3841
}
 
3842
 
 
3843
int VBoxGLWidget::vhwaQueryInfo2(struct _VBOXVHWACMD_QUERYINFO2 *pCmd)
 
3844
{
 
3845
    VBOXQGLLOG_ENTER(("\n"));
 
3846
 
 
3847
    const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(context());
 
3848
 
 
3849
    Assert(pCmd->numFourCC >= (uint32_t)info.getFourccSupportedCount());
 
3850
    if(pCmd->numFourCC < (uint32_t)info.getFourccSupportedCount())
 
3851
        return VERR_GENERAL_FAILURE;
 
3852
 
 
3853
    pCmd->numFourCC = (uint32_t)info.getFourccSupportedCount();
 
3854
    for(int i = 0; i < info.getFourccSupportedCount(); i++)
 
3855
    {
 
3856
        pCmd->FourCC[i] = info.getFourccSupportedList()[i];
 
3857
    }
 
3858
    return VINF_SUCCESS;
 
3859
}
 
3860
 
 
3861
static DECLCALLBACK(void) vboxQGLSaveExec(PSSMHANDLE pSSM, void *pvUser)
 
3862
{
 
3863
    VBoxGLWidget * pw = (VBoxGLWidget*)pvUser;
 
3864
    pw->vhwaSaveExec(pSSM);
 
3865
}
 
3866
 
 
3867
static DECLCALLBACK(int) vboxQGLLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
 
3868
{
 
3869
    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
 
3870
    VBoxGLWidget * pw = (VBoxGLWidget*)pvUser;
 
3871
    return VBoxGLWidget::vhwaLoadExec(&pw->onResizeCmdList(), pSSM, u32Version);
 
3872
}
 
3873
 
 
3874
int VBoxGLWidget::vhwaSaveSurface(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps)
 
3875
{
 
3876
    VBOXQGL_SAVE_SURFSTART(pSSM);
 
3877
 
 
3878
    uint64_t u64 = vboxVRAMOffset(pSurf);
 
3879
    int rc;
 
3880
    rc = SSMR3PutU32(pSSM, pSurf->handle());         AssertRC(rc);
 
3881
    rc = SSMR3PutU64(pSSM, u64);         AssertRC(rc);
 
3882
    rc = SSMR3PutU32(pSSM, pSurf->width());         AssertRC(rc);
 
3883
    rc = SSMR3PutU32(pSSM, pSurf->height());         AssertRC(rc);
 
3884
    rc = SSMR3PutU32(pSSM, surfCaps);         AssertRC(rc);
 
3885
    uint32_t flags = 0;
 
3886
    const VBoxVHWAColorKey * pDstBltCKey = pSurf->dstBltCKey();
 
3887
    const VBoxVHWAColorKey * pSrcBltCKey = pSurf->srcBltCKey();
 
3888
    const VBoxVHWAColorKey * pDstOverlayCKey = pSurf->dstOverlayCKey();
 
3889
    const VBoxVHWAColorKey * pSrcOverlayCKey = pSurf->srcOverlayCKey();
 
3890
    if(pDstBltCKey)
 
3891
    {
 
3892
        flags |= VBOXVHWA_SD_CKDESTBLT;
 
3893
    }
 
3894
    if(pSrcBltCKey)
 
3895
    {
 
3896
        flags |= VBOXVHWA_SD_CKSRCBLT;
 
3897
    }
 
3898
    if(pDstOverlayCKey)
 
3899
    {
 
3900
        flags |= VBOXVHWA_SD_CKDESTOVERLAY;
 
3901
    }
 
3902
    if(pSrcOverlayCKey)
 
3903
    {
 
3904
        flags |= VBOXVHWA_SD_CKSRCOVERLAY;
 
3905
    }
 
3906
 
 
3907
    rc = SSMR3PutU32(pSSM, flags);         AssertRC(rc);
 
3908
    if(pDstBltCKey)
 
3909
    {
 
3910
        rc = SSMR3PutU32(pSSM, pDstBltCKey->lower());         AssertRC(rc);
 
3911
        rc = SSMR3PutU32(pSSM, pDstBltCKey->upper());         AssertRC(rc);
 
3912
    }
 
3913
    if(pSrcBltCKey)
 
3914
    {
 
3915
        rc = SSMR3PutU32(pSSM, pSrcBltCKey->lower());         AssertRC(rc);
 
3916
        rc = SSMR3PutU32(pSSM, pSrcBltCKey->upper());         AssertRC(rc);
 
3917
    }
 
3918
    if(pDstOverlayCKey)
 
3919
    {
 
3920
        rc = SSMR3PutU32(pSSM, pDstOverlayCKey->lower());         AssertRC(rc);
 
3921
        rc = SSMR3PutU32(pSSM, pDstOverlayCKey->upper());         AssertRC(rc);
 
3922
    }
 
3923
    if(pSrcOverlayCKey)
 
3924
    {
 
3925
        rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->lower());         AssertRC(rc);
 
3926
        rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->upper());         AssertRC(rc);
 
3927
    }
 
3928
 
 
3929
    const VBoxVHWAColorFormat & format = pSurf->colorFormat();
 
3930
    flags = 0;
 
3931
    if(format.fourcc())
 
3932
    {
 
3933
        flags |= VBOXVHWA_PF_FOURCC;
 
3934
        rc = SSMR3PutU32(pSSM, flags);         AssertRC(rc);
 
3935
        rc = SSMR3PutU32(pSSM, format.fourcc());         AssertRC(rc);
 
3936
    }
 
3937
    else
 
3938
    {
 
3939
        flags |= VBOXVHWA_PF_RGB;
 
3940
        rc = SSMR3PutU32(pSSM, flags);         AssertRC(rc);
 
3941
        rc = SSMR3PutU32(pSSM, format.bitsPerPixel());         AssertRC(rc);
 
3942
        rc = SSMR3PutU32(pSSM, format.r().mask());         AssertRC(rc);
 
3943
        rc = SSMR3PutU32(pSSM, format.g().mask());         AssertRC(rc);
 
3944
        rc = SSMR3PutU32(pSSM, format.b().mask());         AssertRC(rc);
 
3945
        rc = SSMR3PutU32(pSSM, format.a().mask());         AssertRC(rc);
 
3946
    }
 
3947
 
 
3948
    VBOXQGL_SAVE_SURFSTOP(pSSM);
 
3949
 
 
3950
    return rc;
 
3951
}
 
3952
 
 
3953
int VBoxGLWidget::vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t cBackBuffers, uint32_t u32Version)
 
3954
{
 
3955
    Q_UNUSED(u32Version);
 
3956
 
 
3957
    VBOXQGL_LOAD_SURFSTART(pSSM);
 
3958
 
 
3959
    char *buf = (char*)malloc(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
 
3960
    memset(buf, 0, sizeof(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)));
 
3961
    VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
 
3962
    pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_CREATE;
 
3963
    pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
 
3964
 
 
3965
    VBOXVHWACMD_SURF_CREATE * pCreateSurf = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
 
3966
    int rc;
 
3967
    uint32_t u32;
 
3968
    rc = SSMR3GetU32(pSSM, &u32);         AssertRC(rc);
 
3969
    pCreateSurf->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)u32;
 
3970
    if(RT_SUCCESS(rc))
 
3971
    {
 
3972
        rc = SSMR3GetU64(pSSM, &pCreateSurf->SurfInfo.offSurface);         AssertRC(rc);
 
3973
        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.width);         AssertRC(rc);
 
3974
        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.height);         AssertRC(rc);
 
3975
        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.surfCaps);         AssertRC(rc);
 
3976
        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.flags);         AssertRC(rc);
 
3977
        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
 
3978
        {
 
3979
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.low);         AssertRC(rc);
 
3980
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.high);         AssertRC(rc);
 
3981
        }
 
3982
        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
 
3983
        {
 
3984
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.low);         AssertRC(rc);
 
3985
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.high);         AssertRC(rc);
 
3986
        }
 
3987
        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
 
3988
        {
 
3989
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.low);         AssertRC(rc);
 
3990
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.high);         AssertRC(rc);
 
3991
        }
 
3992
        if(pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
 
3993
        {
 
3994
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.low);         AssertRC(rc);
 
3995
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.high);         AssertRC(rc);
 
3996
        }
 
3997
 
 
3998
        rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.flags);         AssertRC(rc);
 
3999
        if(pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
 
4000
        {
 
4001
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.c.rgbBitCount);         AssertRC(rc);
 
4002
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m1.rgbRBitMask);         AssertRC(rc);
 
4003
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m2.rgbGBitMask);         AssertRC(rc);
 
4004
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m3.rgbBBitMask);         AssertRC(rc);
 
4005
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m4.rgbABitMask);         AssertRC(rc);
 
4006
        }
 
4007
        else if(pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
 
4008
        {
 
4009
            rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.fourCC);         AssertRC(rc);
 
4010
        }
 
4011
        else
 
4012
        {
 
4013
            Assert(0);
 
4014
        }
 
4015
 
 
4016
        if(cBackBuffers)
 
4017
        {
 
4018
            pCreateSurf->SurfInfo.cBackBuffers = cBackBuffers;
 
4019
            pCreateSurf->SurfInfo.surfCaps |= VBOXVHWA_SCAPS_COMPLEX;
 
4020
        }
 
4021
 
 
4022
        pCmdList->push_back(pCmd);
 
4023
//        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
 
4024
//        if(RT_SUCCESS(rc))
 
4025
//        {
 
4026
//            rc = pCmd->rc;
 
4027
//            AssertRC(rc);
 
4028
//        }
 
4029
    }
 
4030
 
 
4031
    VBOXQGL_LOAD_SURFSTOP(pSSM);
 
4032
 
 
4033
    return rc;
 
4034
}
 
4035
 
 
4036
int VBoxGLWidget::vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible)
 
4037
{
 
4038
    VBOXQGL_SAVE_OVERLAYSTART(pSSM);
 
4039
 
 
4040
    uint32_t flags = 0;
 
4041
    const VBoxVHWAColorKey * dstCKey = pSurf->dstOverlayCKey();
 
4042
    const VBoxVHWAColorKey * defaultDstCKey = pSurf->defaultDstOverlayCKey();
 
4043
    const VBoxVHWAColorKey * srcCKey = pSurf->srcOverlayCKey();;
 
4044
    const VBoxVHWAColorKey * defaultSrcCKey = pSurf->defaultSrcOverlayCKey();
 
4045
    bool bSaveDstCKey = false;
 
4046
    bool bSaveSrcCKey = false;
 
4047
 
 
4048
    if(bVisible)
 
4049
    {
 
4050
        flags |= VBOXVHWA_OVER_SHOW;
 
4051
    }
 
4052
    else
 
4053
    {
 
4054
        flags |= VBOXVHWA_OVER_HIDE;
 
4055
    }
 
4056
 
 
4057
    if(!dstCKey)
 
4058
    {
 
4059
        flags |= VBOXVHWA_OVER_KEYDEST;
 
4060
    }
 
4061
    else if(defaultDstCKey)
 
4062
    {
 
4063
        flags |= VBOXVHWA_OVER_KEYDESTOVERRIDE;
 
4064
        bSaveDstCKey = true;
 
4065
    }
 
4066
 
 
4067
    if(srcCKey == defaultSrcCKey)
 
4068
    {
 
4069
        flags |= VBOXVHWA_OVER_KEYSRC;
 
4070
    }
 
4071
    else if(srcCKey)
 
4072
    {
 
4073
        flags |= VBOXVHWA_OVER_KEYSRCOVERRIDE;
 
4074
        bSaveSrcCKey = true;
 
4075
    }
 
4076
 
 
4077
    int rc = SSMR3PutU32(pSSM, flags); AssertRC(rc);
 
4078
 
 
4079
    rc = SSMR3PutU32(pSSM, mDisplay.getPrimary()->handle()); AssertRC(rc);
 
4080
    rc = SSMR3PutU32(pSSM, pSurf->handle()); AssertRC(rc);
 
4081
 
 
4082
    if(bSaveDstCKey)
 
4083
    {
 
4084
        rc = SSMR3PutU32(pSSM, dstCKey->lower()); AssertRC(rc);
 
4085
        rc = SSMR3PutU32(pSSM, dstCKey->upper()); AssertRC(rc);
 
4086
    }
 
4087
    if(bSaveSrcCKey)
 
4088
    {
 
4089
        rc = SSMR3PutU32(pSSM, srcCKey->lower()); AssertRC(rc);
 
4090
        rc = SSMR3PutU32(pSSM, srcCKey->upper()); AssertRC(rc);
 
4091
    }
 
4092
 
 
4093
    int x1, x2, y1, y2;
 
4094
    pSurf->targRect().getCoords(&x1, &y1, &x2, &y2);
 
4095
    rc = SSMR3PutS32(pSSM, x1); AssertRC(rc);
 
4096
    rc = SSMR3PutS32(pSSM, x2+1); AssertRC(rc);
 
4097
    rc = SSMR3PutS32(pSSM, y1); AssertRC(rc);
 
4098
    rc = SSMR3PutS32(pSSM, y2+1); AssertRC(rc);
 
4099
 
 
4100
    pSurf->srcRect().getCoords(&x1, &y1, &x2, &y2);
 
4101
    rc = SSMR3PutS32(pSSM, x1); AssertRC(rc);
 
4102
    rc = SSMR3PutS32(pSSM, x2+1); AssertRC(rc);
 
4103
    rc = SSMR3PutS32(pSSM, y1); AssertRC(rc);
 
4104
    rc = SSMR3PutS32(pSSM, y2+1); AssertRC(rc);
 
4105
 
 
4106
    VBOXQGL_SAVE_OVERLAYSTOP(pSSM);
 
4107
 
 
4108
    return rc;
 
4109
}
 
4110
 
 
4111
int VBoxGLWidget::vhwaLoadOverlayData(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
 
4112
{
 
4113
    Q_UNUSED(u32Version);
 
4114
 
 
4115
    VBOXQGL_LOAD_OVERLAYSTART(pSSM);
 
4116
 
 
4117
//    char buf[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_OVERLAY_UPDATE)];
 
4118
    char *buf = new char[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)];
 
4119
    memset(buf, 0, VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
 
4120
    VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
 
4121
    pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE;
 
4122
    pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
 
4123
 
 
4124
    VBOXVHWACMD_SURF_OVERLAY_UPDATE * pUpdateOverlay = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
 
4125
    int rc;
 
4126
 
 
4127
    rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.flags); AssertRC(rc);
 
4128
    uint32_t hSrc, hDst;
 
4129
    rc = SSMR3GetU32(pSSM, &hDst); AssertRC(rc);
 
4130
    rc = SSMR3GetU32(pSSM, &hSrc); AssertRC(rc);
 
4131
    pUpdateOverlay->u.in.hSrcSurf = hSrc;
 
4132
    pUpdateOverlay->u.in.hDstSurf = hDst;
 
4133
//    Assert(hDst == mDisplay.getVGA()->handle());
 
4134
//    VBoxVHWASurfaceBase *pDstSurf = handle2Surface(hDst);
 
4135
//    VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(hSrc);
 
4136
//    Assert(pSrcSurf);
 
4137
//    Assert(pDstSurf);
 
4138
//    if(pSrcSurf && pDstSurf)
 
4139
    {
 
4140
        pUpdateOverlay->u.in.offDstSurface = VBOXVHWA_OFFSET64_VOID;
 
4141
//        vboxVRAMOffset(pDstSurf);
 
4142
        pUpdateOverlay->u.in.offSrcSurface = VBOXVHWA_OFFSET64_VOID;
 
4143
//        vboxVRAMOffset(pSrcSurf);
 
4144
 
 
4145
        if(pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
 
4146
        {
 
4147
            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.low); AssertRC(rc);
 
4148
            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.high); AssertRC(rc);
 
4149
        }
 
4150
 
 
4151
        if(pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
 
4152
        {
 
4153
            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.low); AssertRC(rc);
 
4154
            rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.high); AssertRC(rc);
 
4155
        }
 
4156
 
 
4157
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.left); AssertRC(rc);
 
4158
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.right); AssertRC(rc);
 
4159
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.top); AssertRC(rc);
 
4160
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.bottom); AssertRC(rc);
 
4161
 
 
4162
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.left); AssertRC(rc);
 
4163
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.right); AssertRC(rc);
 
4164
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.top); AssertRC(rc);
 
4165
        rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.bottom); AssertRC(rc);
 
4166
 
 
4167
        pCmdList->push_back(pCmd);
 
4168
//        vboxExecOnResize(&VBoxGLWidget::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
 
4169
//        if(RT_SUCCESS(rc))
 
4170
//        {
 
4171
//            rc = pCmd->rc;
 
4172
//            AssertRC(rc);
 
4173
//        }
 
4174
    }
 
4175
//    else
 
4176
//    {
 
4177
//        rc = VERR_GENERAL_FAILURE;
 
4178
//    }
 
4179
 
 
4180
    VBOXQGL_LOAD_OVERLAYSTOP(pSSM);
 
4181
 
 
4182
    return rc;
 
4183
}
 
4184
 
 
4185
void VBoxGLWidget::vhwaSaveExecVoid(struct SSMHANDLE * pSSM)
 
4186
{
 
4187
    VBOXQGL_SAVE_START(pSSM);
 
4188
    int rc = SSMR3PutU32(pSSM, 0);         AssertRC(rc); /* 0 primaries */
 
4189
    VBOXQGL_SAVE_STOP(pSSM);
 
4190
}
 
4191
 
 
4192
void VBoxGLWidget::vhwaSaveExec(struct SSMHANDLE * pSSM)
 
4193
{
 
4194
    VBOXQGL_SAVE_START(pSSM);
 
4195
 
 
4196
    /* the mechanism of restoring data is based on generating VHWA commands that restore the surfaces state
 
4197
     * the following commands are generated:
 
4198
     * I.    CreateSurface
 
4199
     * II.   UpdateOverlay
 
4200
     *
 
4201
     * Data format is the following:
 
4202
     * I.    u32 - Num primary surfaces - (the current frontbuffer is detected in the stored surf flags which are posted to the generated CreateSurface cmd)
 
4203
     * II.   for each primary surf
 
4204
     * II.1    generate & execute CreateSurface cmd (see below on the generation logic)
 
4205
     * III.  u32 - Num overlays
 
4206
     * IV.   for each overlay
 
4207
     * IV.1    u32 - Num surfaces in overlay (the current frontbuffer is detected in the stored surf flags which are posted to the generated CreateSurface cmd)
 
4208
     * IV.2    for each surface in overlay
 
4209
     * IV.2.a    generate & execute CreateSurface cmd (see below on the generation logic)
 
4210
     * IV.2.b    generate & execute UpdateOverlay cmd (see below on the generation logic)
 
4211
     *
 
4212
     */
 
4213
    const SurfList & primaryList = mDisplay.primaries().surfaces();
 
4214
    uint32_t cPrimary = (uint32_t)primaryList.size();
 
4215
    if(cPrimary &&
 
4216
            (mDisplay.getVGA() == NULL || mDisplay.getVGA()->handle() == VBOXVHWA_SURFHANDLE_INVALID))
 
4217
    {
 
4218
        cPrimary -= 1;
 
4219
    }
 
4220
 
 
4221
    int rc = SSMR3PutU32(pSSM, cPrimary);         AssertRC(rc);
 
4222
    if(cPrimary)
 
4223
    {
 
4224
        for (SurfList::const_iterator pr = primaryList.begin();
 
4225
             pr != primaryList.end(); ++ pr)
 
4226
        {
 
4227
            VBoxVHWASurfaceBase *pSurf = *pr;
 
4228
    //        bool bVga = (pSurf == mDisplay.getVGA());
 
4229
            bool bVisible = (pSurf == mDisplay.getPrimary());
 
4230
            uint32_t flags = VBOXVHWA_SCAPS_PRIMARYSURFACE;
 
4231
            if(bVisible)
 
4232
                flags |= VBOXVHWA_SCAPS_VISIBLE;
 
4233
 
 
4234
            if(pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID)
 
4235
            {
 
4236
                rc = vhwaSaveSurface(pSSM, *pr, flags);    AssertRC(rc);
 
4237
#ifdef DEBUG
 
4238
                --cPrimary;
 
4239
                Assert(cPrimary < UINT32_MAX / 2);
 
4240
#endif
 
4241
            }
 
4242
            else
 
4243
            {
 
4244
                Assert(pSurf == mDisplay.getVGA());
 
4245
            }
 
4246
        }
 
4247
 
 
4248
#ifdef DEBUG
 
4249
        Assert(!cPrimary);
 
4250
#endif
 
4251
 
 
4252
        const OverlayList & overlays = mDisplay.overlays();
 
4253
        rc = SSMR3PutU32(pSSM, (uint32_t)overlays.size());         AssertRC(rc);
 
4254
 
 
4255
        for (OverlayList::const_iterator it = overlays.begin();
 
4256
             it != overlays.end(); ++ it)
 
4257
        {
 
4258
            VBoxVHWASurfList * pSurfList = *it;
 
4259
            const SurfList & surfaces = pSurfList->surfaces();
 
4260
            uint32_t cSurfs = (uint32_t)surfaces.size();
 
4261
            uint32_t flags = VBOXVHWA_SCAPS_OVERLAY;
 
4262
            if(cSurfs > 1)
 
4263
                flags |= VBOXVHWA_SCAPS_COMPLEX;
 
4264
            rc = SSMR3PutU32(pSSM, cSurfs);         AssertRC(rc);
 
4265
            for (SurfList::const_iterator sit = surfaces.begin();
 
4266
                 sit != surfaces.end(); ++ sit)
 
4267
            {
 
4268
                rc = vhwaSaveSurface(pSSM, *sit, flags);    AssertRC(rc);
 
4269
            }
 
4270
 
 
4271
            bool bVisible = true;
 
4272
            VBoxVHWASurfaceBase * pOverlayData = pSurfList->current();
 
4273
            if(!pOverlayData)
 
4274
            {
 
4275
                pOverlayData = surfaces.front();
 
4276
                bVisible = false;
 
4277
            }
 
4278
 
 
4279
            rc = vhwaSaveOverlayData(pSSM, pOverlayData, bVisible);    AssertRC(rc);
 
4280
        }
 
4281
    }
 
4282
 
 
4283
    VBOXQGL_SAVE_STOP(pSSM);
 
4284
}
 
4285
 
 
4286
int VBoxGLWidget::vhwaLoadVHWAEnable(VHWACommandList * pCmdList)
 
4287
{
 
4288
    char *buf = (char*)malloc(sizeof(VBOXVHWACMD));
 
4289
    Assert(buf);
 
4290
    if(buf)
 
4291
    {
 
4292
        memset(buf, 0, sizeof(VBOXVHWACMD));
 
4293
        VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
 
4294
        pCmd->enmCmd = VBOXVHWACMD_TYPE_ENABLE;
 
4295
        pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
 
4296
        pCmdList->push_back(pCmd);
 
4297
        return VINF_SUCCESS;
 
4298
    }
 
4299
 
 
4300
    return VERR_OUT_OF_RESOURCES;
 
4301
}
 
4302
 
 
4303
int VBoxGLWidget::vhwaLoadExec(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
 
4304
{
 
4305
    VBOXQGL_LOAD_START(pSSM);
 
4306
 
 
4307
    if(u32Version > VBOXQGL_STATE_VERSION)
 
4308
        return VERR_VERSION_MISMATCH;
 
4309
 
 
4310
    int rc;
 
4311
    uint32_t u32;
 
4312
 
 
4313
    rc = vhwaLoadVHWAEnable(pCmdList); AssertRC(rc);
 
4314
    if(RT_SUCCESS(rc))
 
4315
    {
 
4316
        rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
 
4317
        if(RT_SUCCESS(rc))
 
4318
        {
 
4319
            if(u32Version == 1 && u32 == (~0)) /* work around the v1 bug */
 
4320
                u32 = 0;
 
4321
            if(u32)
 
4322
            {
 
4323
                for(uint32_t i = 0; i < u32; ++i)
 
4324
                {
 
4325
                    rc = vhwaLoadSurface(pCmdList, pSSM, 0, u32Version);  AssertRC(rc);
 
4326
                    if(RT_FAILURE(rc))
 
4327
                        break;
 
4328
                }
 
4329
 
 
4330
                if(RT_SUCCESS(rc))
 
4331
                {
 
4332
                    rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
 
4333
                    if(RT_SUCCESS(rc))
 
4334
                    {
 
4335
                        for(uint32_t i = 0; i < u32; ++i)
 
4336
                        {
 
4337
                            uint32_t cSurfs;
 
4338
                            rc = SSMR3GetU32(pSSM, &cSurfs); AssertRC(rc);
 
4339
                            for(uint32_t j = 0; j < cSurfs; ++j)
 
4340
                            {
 
4341
                                rc = vhwaLoadSurface(pCmdList, pSSM, cSurfs - 1, u32Version);  AssertRC(rc);
 
4342
                                if(RT_FAILURE(rc))
 
4343
                                    break;
 
4344
                            }
 
4345
 
 
4346
                            if(RT_SUCCESS(rc))
 
4347
                            {
 
4348
                                rc = vhwaLoadOverlayData(pCmdList, pSSM, u32Version);  AssertRC(rc);
 
4349
                            }
 
4350
 
 
4351
                            if(RT_FAILURE(rc))
 
4352
                            {
 
4353
                                break;
 
4354
                            }
 
4355
                        }
 
4356
                    }
 
4357
                }
 
4358
            }
 
4359
#ifdef VBOXQGL_STATE_DEBUG
 
4360
            else if(u32Version == 1) /* read the 0 overlay count to ensure the following VBOXQGL_LOAD_STOP succeedes */
 
4361
            {
 
4362
                rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
 
4363
                Assert(u32 == 0);
 
4364
            }
 
4365
#endif
 
4366
        }
 
4367
    }
 
4368
 
 
4369
    VBOXQGL_LOAD_STOP(pSSM);
 
4370
 
 
4371
    return rc;
 
4372
}
 
4373
 
 
4374
int VBoxGLWidget::vhwaConstruct(struct _VBOXVHWACMD_HH_CONSTRUCT *pCmd)
 
4375
{
 
4376
    PVM pVM = (PVM)pCmd->pVM;
 
4377
    uint32_t intsId = 0; /* @todo: set the proper id */
 
4378
 
 
4379
    char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
 
4380
 
 
4381
    char * pszName = nameFuf;
 
4382
    sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
 
4383
    int rc = SSMR3RegisterExternal(
 
4384
            pVM,                    /* The VM handle*/
 
4385
            pszName,                /* Data unit name. */
 
4386
            intsId,                 /* The instance identifier of the data unit.
 
4387
                                     * This must together with the name be unique. */
 
4388
            VBOXQGL_STATE_VERSION,   /* Data layout version number. */
 
4389
            128,             /* The approximate amount of data in the unit.
 
4390
                              * Only for progress indicators. */
 
4391
            NULL, NULL, NULL, /* pfnLiveXxx */
 
4392
            NULL,            /* Prepare save callback, optional. */
 
4393
            vboxQGLSaveExec, /* Execute save callback, optional. */
 
4394
            NULL,            /* Done save callback, optional. */
 
4395
            NULL,            /* Prepare load callback, optional. */
 
4396
            vboxQGLLoadExec, /* Execute load callback, optional. */
 
4397
            NULL,            /* Done load callback, optional. */
 
4398
            this             /* User argument. */
 
4399
            );
 
4400
    Assert(RT_SUCCESS(rc));
 
4401
    return rc;
 
4402
}
 
4403
 
 
4404
uchar * VBoxGLWidget::vboxVRAMAddressFromOffset(uint64_t offset)
 
4405
{
 
4406
    return ((offset != VBOXVHWA_OFFSET64_VOID) && vboxUsesGuestVRAM()) ? vboxAddress() + offset : NULL;
 
4407
}
 
4408
 
 
4409
uint64_t VBoxGLWidget::vboxVRAMOffsetFromAddress(uchar* addr)
 
4410
{
 
4411
    return uint64_t(addr - vboxAddress());
 
4412
}
 
4413
 
 
4414
uint64_t VBoxGLWidget::vboxVRAMOffset(VBoxVHWASurfaceBase * pSurf)
 
4415
{
 
4416
    return pSurf->addressAlocated() ? VBOXVHWA_OFFSET64_VOID : vboxVRAMOffsetFromAddress(pSurf->address());
 
4417
}
 
4418
 
 
4419
#endif
 
4420
 
 
4421
void VBoxGLWidget::initializeGL()
 
4422
{
 
4423
    vboxVHWAGetSupportInfo(context());
 
4424
    VBoxVHWASurfaceBase::globalInit();
 
4425
}
 
4426
 
 
4427
#ifdef VBOXQGL_DBG_SURF
 
4428
 
 
4429
int g_iCur = 0;
 
4430
VBoxVHWASurfaceBase * g_apSurf[] = {NULL, NULL, NULL};
 
4431
 
 
4432
void VBoxGLWidget::vboxDoTestSurfaces(void* context)
 
4433
{
 
4434
//    uint32_t width = 103;
 
4435
//    uint32_t height = 47;
 
4436
//    uint32_t rgbBitCount = 32;
 
4437
//    uint32_t r = 0xff, g = 0xff00, b = 0xff0000;
 
4438
//    QRect dstRect(10, 50, width, height);
 
4439
//    QRect srcRect(0, 0, width, height);
 
4440
////    Assert(0);
 
4441
//    if(!pSurf1)
 
4442
//    {
 
4443
//
 
4444
////        pSurf1 = new VBoxVHWASurfaceBase(this, width, height,
 
4445
////                        VBoxVHWAColorFormat(rgbBitCount,
 
4446
////                                r,
 
4447
////                                g,
 
4448
////                                b),
 
4449
////                        NULL, NULL, NULL, NULL);
 
4450
//        pSurf1 = new VBoxVHWASurfaceBase(this, &QSize(width, height),
 
4451
////                        ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) ? mDisplay.getPrimary()->rect().size() : &QSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height)),
 
4452
//                        &mDisplay.getPrimary()->rect().size(),
 
4453
//                        VBoxVHWAColorFormat(rgbBitCount,
 
4454
//                                r,
 
4455
//                                g,
 
4456
//                                b),
 
4457
////                        pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey);
 
4458
//                        NULL, NULL, NULL, NULL);
 
4459
//
 
4460
//        pSurf1->init(mDisplay.getVGA(), NULL);
 
4461
//
 
4462
//        VBoxVHWASurfList *pConstructingList = new VBoxVHWASurfList();
 
4463
//        mDisplay.addOverlay(pConstructingList);
 
4464
//        pConstructingList->add(pSurf1);
 
4465
//        pConstructingList->setCurrentVisible(pSurf1);
 
4466
////        pSurf1->performDisplay();
 
4467
//    }
 
4468
//
 
4469
////    pDisplay->blt(&dstRect, pSurf1, &srcRect, NULL, NULL);
 
4470
////    pDisplay->performDisplay();
 
4471
    if(g_iCur >= RT_ELEMENTS(g_apSurf))
 
4472
        g_iCur = 0;
 
4473
    VBoxVHWASurfaceBase * pSurf1 = g_apSurf[g_iCur];
 
4474
    if(pSurf1)
 
4475
    {
 
4476
        pSurf1->getComplexList()->setCurrentVisible(pSurf1);
 
4477
    }
 
4478
}
 
4479
#endif
 
4480
 
 
4481
void VBoxGLWidget::vboxDoUpdateViewport(const QRect & aRect)
 
4482
{
 
4483
    adjustViewport(mDisplay.getPrimary()->size(), aRect);
 
4484
    mViewport = aRect;
 
4485
 
 
4486
    const SurfList & primaryList = mDisplay.primaries().surfaces();
 
4487
 
 
4488
    for (SurfList::const_iterator pr = primaryList.begin();
 
4489
         pr != primaryList.end(); ++ pr)
 
4490
    {
 
4491
        VBoxVHWASurfaceBase *pSurf = *pr;
 
4492
        pSurf->updateVisibility(NULL, aRect, false, false);
 
4493
    }
 
4494
 
 
4495
    const OverlayList & overlays = mDisplay.overlays();
 
4496
    QRect overInter = overlaysRectIntersection();
 
4497
    overInter = overInter.intersect(aRect);
 
4498
 
 
4499
    bool bDisplayPrimary = true;
 
4500
 
 
4501
    for (OverlayList::const_iterator it = overlays.begin();
 
4502
         it != overlays.end(); ++ it)
 
4503
    {
 
4504
        VBoxVHWASurfList * pSurfList = *it;
 
4505
        const SurfList & surfaces = pSurfList->surfaces();
 
4506
        if(surfaces.size())
 
4507
        {
 
4508
            bool bNotIntersected = !overInter.isEmpty() && surfaces.front()->targRect().contains(overInter);
 
4509
            Assert(bNotIntersected);
 
4510
 
 
4511
            bDisplayPrimary &= !bNotIntersected;
 
4512
            for (SurfList::const_iterator sit = surfaces.begin();
 
4513
                 sit != surfaces.end(); ++ sit)
 
4514
            {
 
4515
                VBoxVHWASurfaceBase *pSurf = *sit;
 
4516
                pSurf->updateVisibility(mDisplay.getPrimary(), aRect, bNotIntersected, false);
 
4517
            }
 
4518
        }
 
4519
    }
 
4520
 
 
4521
    Assert(!bDisplayPrimary);
 
4522
    mDisplay.setDisplayPrimary(bDisplayPrimary);
 
4523
}
 
4524
 
 
4525
bool VBoxGLWidget::hasSurfaces() const
 
4526
{
 
4527
    if(mDisplay.overlays().size() != 0)
 
4528
        return true;
 
4529
    if(mDisplay.primaries().size() > 1)
 
4530
        return true;
 
4531
    return mDisplay.getVGA()->handle() != VBOXVHWA_SURFHANDLE_INVALID;
 
4532
}
 
4533
 
 
4534
bool VBoxGLWidget::hasVisibleOverlays()
 
4535
{
 
4536
    const OverlayList & overlays = mDisplay.overlays();
 
4537
    for (OverlayList::const_iterator it = overlays.begin();
 
4538
         it != overlays.end(); ++ it)
 
4539
    {
 
4540
        VBoxVHWASurfList * pSurfList = *it;
 
4541
        if(pSurfList->current() != NULL)
 
4542
            return true;
 
4543
    }
 
4544
    return false;
 
4545
}
 
4546
 
 
4547
QRect VBoxGLWidget::overlaysRectUnion()
 
4548
{
 
4549
    const OverlayList & overlays = mDisplay.overlays();
 
4550
    VBoxVHWADirtyRect un;
 
4551
    for (OverlayList::const_iterator it = overlays.begin();
 
4552
         it != overlays.end(); ++ it)
 
4553
    {
 
4554
        VBoxVHWASurfaceBase * pOverlay = (*it)->current();
 
4555
        if(pOverlay != NULL)
 
4556
        {
 
4557
            un.add(pOverlay->targRect());
 
4558
        }
 
4559
    }
 
4560
    return un.toRect();
 
4561
}
 
4562
 
 
4563
QRect VBoxGLWidget::overlaysRectIntersection()
 
4564
{
 
4565
    const OverlayList & overlays = mDisplay.overlays();
 
4566
    QRect rect;
 
4567
    VBoxVHWADirtyRect un;
 
4568
    for (OverlayList::const_iterator it = overlays.begin();
 
4569
         it != overlays.end(); ++ it)
 
4570
    {
 
4571
        VBoxVHWASurfaceBase * pOverlay = (*it)->current();
 
4572
        if(pOverlay != NULL)
 
4573
        {
 
4574
            if(rect.isNull())
 
4575
            {
 
4576
                rect = pOverlay->targRect();
 
4577
            }
 
4578
            else
 
4579
            {
 
4580
                rect = rect.intersected(pOverlay->targRect());
 
4581
                if(rect.isNull())
 
4582
                    break;
 
4583
            }
 
4584
        }
 
4585
    }
 
4586
    return rect;
 
4587
}
 
4588
 
 
4589
//void VBoxGLWidget::vboxDoPaint(void *pe)
 
4590
//{
 
4591
//    Q_UNUSED(pe);
 
4592
//
 
4593
//#ifdef VBOXQGL_DBG_SURF
 
4594
//    vboxDoTestSurfaces(NULL);
 
4595
//#endif
 
4596
////#ifdef VBOXQGL_PROF_BASE
 
4597
////    vboxDoUpdateRect(&((QPaintEvent*)pe)->rect());
 
4598
////#endif
 
4599
////    mDisplay.performDisplay();
 
4600
//}
 
4601
 
 
4602
void VBoxGLWidget::vboxDoUpdateRect(const QRect * pRect)
 
4603
{
 
4604
    mDisplay.getPrimary()->updatedMem(pRect);
 
4605
}
 
4606
 
 
4607
void VBoxGLWidget::vboxDoResize(void *resize)
 
4608
{
 
4609
//    Assert(!format().accum());
 
4610
//    Assert(format().alpha());
 
4611
//    Assert(format().alphaBufferSize() == 8);
 
4612
    VBOXQGLLOG(("format().blueBufferSize()(%d)\n", format().blueBufferSize()));
 
4613
    VBOXQGLLOG(("format().greenBufferSize()(%d)\n", format().greenBufferSize()));
 
4614
    VBOXQGLLOG(("format().redBufferSize()(%d)\n", format().redBufferSize()));
 
4615
#ifdef DEBUG_misha
 
4616
    Assert(format().blueBufferSize() == 8);
 
4617
    Assert(format().greenBufferSize() == 8);
 
4618
    Assert(format().redBufferSize() == 8);
 
4619
#endif
 
4620
 
 
4621
//    Assert(!format().depth());
 
4622
    Assert(format().directRendering());
 
4623
    Assert(format().doubleBuffer());
 
4624
    Assert(format().hasOpenGL());
 
4625
    VBOXQGLLOG(("hasOpenGLOverlays(%d), hasOverlay(%d)\n", format().hasOpenGLOverlays(), format().hasOverlay()));
 
4626
//    Assert(format().hasOpenGLOverlays());
 
4627
//    Assert(format().hasOverlay());
 
4628
    Assert(format().plane() == 0);
 
4629
    Assert(format().rgba());
 
4630
    Assert(!format().sampleBuffers());
 
4631
//    Assert(!format().stencil());
 
4632
    Assert(!format().stereo());
 
4633
    VBOXQGLLOG(("swapInterval(%d)\n", format().swapInterval()));
 
4634
//    Assert(format().swapInterval() == 0);
 
4635
 
 
4636
 
 
4637
    VBOXQGL_CHECKERR(
 
4638
            vboxglActiveTexture(GL_TEXTURE0);
 
4639
        );
 
4640
 
 
4641
    VBoxResizeEvent *re = (VBoxResizeEvent*)resize;
 
4642
    bool remind = false;
 
4643
    bool fallback = false;
 
4644
 
 
4645
    VBOXQGLLOG(("resizing: fmt=%d, vram=%p, bpp=%d, bpl=%d, width=%d, height=%d\n",
 
4646
                      re->pixelFormat(), re->VRAM(),
 
4647
                      re->bitsPerPixel(), re->bytesPerLine(),
 
4648
                      re->width(), re->height()));
 
4649
 
 
4650
    /* clean the old values first */
 
4651
 
 
4652
    ulong bytesPerLine;
 
4653
    uint32_t bitsPerPixel;
 
4654
    uint32_t b = 0xff, g = 0xff00, r = 0xff0000;
 
4655
 
 
4656
    /* check if we support the pixel format and can use the guest VRAM directly */
 
4657
    if (re->pixelFormat() == FramebufferPixelFormat_FOURCC_RGB)
 
4658
    {
 
4659
 
 
4660
        bitsPerPixel = re->bitsPerPixel();
 
4661
        bytesPerLine = re->bytesPerLine();
 
4662
        ulong bitsPerLine = bytesPerLine * 8;
 
4663
 
 
4664
        switch (bitsPerPixel)
 
4665
        {
 
4666
            case 32:
 
4667
//                format = VBoxVHWAColorFormat(bitsPerPixel, 0xff, 0xff00, 0xff0000);
 
4668
                break;
 
4669
            case 24:
 
4670
#ifdef DEBUG_misha
 
4671
                Assert(0);
 
4672
#endif
 
4673
//                format = VBoxVHWAColorFormat(bitsPerPixel, 0xff, 0xff00, 0xff0000);
 
4674
//                remind = true;
 
4675
                break;
 
4676
//            case 16:
 
4677
//                Assert(0);
 
4678
////                r = 0xf800;
 
4679
////                g = 0x7e0;
 
4680
////                b = 0x1f;
 
4681
//                break;
 
4682
            case 8:
 
4683
#ifdef DEBUG_misha
 
4684
                Assert(0);
 
4685
#endif
 
4686
                g = b = 0;
 
4687
                remind = true;
 
4688
                break;
 
4689
            case 1:
 
4690
#ifdef DEBUG_misha
 
4691
                Assert(0);
 
4692
#endif
 
4693
                r = 1;
 
4694
                g = b = 0;
 
4695
                remind = true;
 
4696
                break;
 
4697
            default:
 
4698
#ifdef DEBUG_misha
 
4699
                Assert(0);
 
4700
#endif
 
4701
                remind = true;
 
4702
                fallback = true;
 
4703
                break;
 
4704
        }
 
4705
 
 
4706
        if (!fallback)
 
4707
        {
 
4708
            /* QImage only supports 32-bit aligned scan lines... */
 
4709
            Assert ((re->bytesPerLine() & 3) == 0);
 
4710
            fallback = ((re->bytesPerLine() & 3) != 0);
 
4711
        }
 
4712
        if (!fallback)
 
4713
        {
 
4714
            /* ...and the scan lines ought to be a whole number of pixels. */
 
4715
            Assert ((bitsPerLine & (re->bitsPerPixel() - 1)) == 0);
 
4716
            fallback = ((bitsPerLine & (re->bitsPerPixel() - 1)) != 0);
 
4717
        }
 
4718
        if (!fallback)
 
4719
        {
 
4720
            // ulong virtWdt = bitsPerLine / re->bitsPerPixel();
 
4721
            mPixelFormat = FramebufferPixelFormat_FOURCC_RGB;
 
4722
            mUsesGuestVRAM = true;
 
4723
        }
 
4724
    }
 
4725
    else
 
4726
    {
 
4727
        fallback = true;
 
4728
    }
 
4729
 
 
4730
    if (fallback)
 
4731
    {
 
4732
        /* we don't support either the pixel format or the color depth,
 
4733
         * fallback to a self-provided 32bpp RGB buffer */
 
4734
        bitsPerPixel = 32;
 
4735
        b = 0xff;
 
4736
        g = 0xff00;
 
4737
        r = 0xff0000;
 
4738
        bytesPerLine = re->width()*bitsPerPixel/8;
 
4739
        mPixelFormat = FramebufferPixelFormat_FOURCC_RGB;
 
4740
//        internalformat = 3;//GL_RGB;
 
4741
//        format = GL_BGRA_EXT;//GL_RGBA;
 
4742
//        type = GL_UNSIGNED_BYTE;
 
4743
        mUsesGuestVRAM = false;
 
4744
    }
 
4745
 
 
4746
    ulong bytesPerPixel = bitsPerPixel/8;
 
4747
    ulong displayWidth = bytesPerLine/bytesPerPixel;
 
4748
    ulong displayHeight = re->height();
 
4749
 
 
4750
#ifdef VBOXQGL_DBG_SURF
 
4751
    for(int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
 
4752
    {
 
4753
        VBoxVHWASurfaceBase * pSurf1 = g_apSurf[i];
 
4754
        if(pSurf1)
 
4755
        {
 
4756
            VBoxVHWASurfList *pConstructingList = pSurf1->getComplexList();
 
4757
            delete pSurf1;
 
4758
            if(pConstructingList)
 
4759
                delete pConstructingList;
 
4760
    //
 
4761
    //            mDisplay.addOverlay(pConstructingList);
 
4762
    //            //            pConstructingList->add(pSurf1);
 
4763
    //            //            pConstructingList->setCurrentVisible(pSurf1);
 
4764
    //            ////            pConstructingList->setCurrentVisible(NULL);
 
4765
        }
 
4766
    }
 
4767
#endif
 
4768
 
 
4769
    VBoxVHWASurfaceBase * pDisplay = mDisplay.setVGA(NULL);
 
4770
    if(pDisplay)
 
4771
        delete pDisplay;
 
4772
 
 
4773
    VBoxVHWAColorFormat format(bitsPerPixel, r,g,b);
 
4774
    QSize dispSize(displayWidth, displayHeight);
 
4775
    QRect dispRect(0, 0, displayWidth, displayHeight);
 
4776
    pDisplay = new VBoxVHWASurfaceBase(this,
 
4777
            dispSize,
 
4778
            dispRect,
 
4779
            dispRect,
 
4780
            dispRect, /* we do not know viewport at the stage of recise, set as a disp rect, it will be updated on repaint */
 
4781
            format,
 
4782
            (VBoxVHWAColorKey*)NULL, (VBoxVHWAColorKey*)NULL, (VBoxVHWAColorKey*)NULL, (VBoxVHWAColorKey*)NULL,
 
4783
#ifdef VBOXVHWA_USE_TEXGROUP
 
4784
            0,
 
4785
#endif
 
4786
            true);
 
4787
    pDisplay->init(NULL, mUsesGuestVRAM ? re->VRAM() : NULL);
 
4788
    mDisplay.setVGA(pDisplay);
 
4789
//    VBOXQGLLOG(("\n\n*******\n\n     viewport size is: (%d):(%d)\n\n*******\n\n", size().width(), size().height()));
 
4790
    mViewport = QRect(0,0,displayWidth, displayHeight);
 
4791
    adjustViewport(dispSize, mViewport);
 
4792
    setupMatricies(dispSize);
 
4793
 
 
4794
#ifdef VBOXQGL_DBG_SURF
 
4795
    {
 
4796
        uint32_t width = 100;
 
4797
        uint32_t height = 60;
 
4798
//        uint32_t rgbBitCount = 32;
 
4799
//        uint32_t r = 0xff, g = 0xff00, b = 0xff0000;
 
4800
//        QRect dstRect(150, 200, width, height);
 
4801
//        QRect srcRect(0, 0, 720, 480);
 
4802
    //    Assert(0);
 
4803
 
 
4804
        for(int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
 
4805
        {
 
4806
            VBoxVHWAColorFormat tmpFormat(FOURCC_YV12);
 
4807
            QSize tmpSize(width, height) ;
 
4808
            VBoxVHWASurfaceBase *pSurf1 = new VBoxVHWASurfaceBase(this, tmpSize,
 
4809
                             mDisplay.getPrimary()->rect(),
 
4810
                             QRect(0, 0, width, height),
 
4811
                             mViewport,
 
4812
                             tmpFormat,
 
4813
                             NULL, NULL, NULL, &VBoxVHWAColorKey(0,0),
 
4814
#ifdef VBOXVHWA_USE_TEXGROUP
 
4815
                             0,
 
4816
#endif
 
4817
                             false);
 
4818
 
 
4819
            Assert(mDisplay.getVGA());
 
4820
            pSurf1->init(mDisplay.getVGA(), NULL);
 
4821
            uchar *addr = pSurf1->address();
 
4822
            uchar cur = 0;
 
4823
            for(uint32_t k = 0; k < width*height; k++)
 
4824
            {
 
4825
                addr[k] = cur;
 
4826
                cur+=64;
 
4827
            }
 
4828
            pSurf1->updatedMem(&QRect(0,0,width, height));
 
4829
//            VBOXQGL_CHECKERR(
 
4830
//                    vboxglActiveTexture(GL_TEXTURE0);
 
4831
//                );
 
4832
 
 
4833
            VBoxVHWASurfList *pConstructingList = new VBoxVHWASurfList();
 
4834
            mDisplay.addOverlay(pConstructingList);
 
4835
            pConstructingList->add(pSurf1);
 
4836
//            pConstructingList->setCurrentVisible(pSurf1);
 
4837
//            pConstructingList->setCurrentVisible(NULL);
 
4838
            g_apSurf[i] = pSurf1;
 
4839
 
 
4840
//            VBoxVHWAGlProgramVHWA * pProgram = vboxVHWAGetGlProgramMngr()->getProgram(true, false, &pSurf1->colorFormat(), &pDisplay->colorFormat());
 
4841
//            pProgram->start();
 
4842
//            pProgram->setSrcTexImgWidth(pSurf1->texRect().width());
 
4843
//            pProgram->stop();
 
4844
        }
 
4845
//        else
 
4846
//        {
 
4847
//            VBoxVHWASurfList *pConstructingList = pSurf1->getComplexList();
 
4848
//            mDisplay.addOverlay(pConstructingList);
 
4849
//            pConstructingList->add(pSurf1);
 
4850
//            pConstructingList->setCurrentVisible(pSurf1);
 
4851
////            pConstructingList->setCurrentVisible(NULL);
 
4852
//        }
 
4853
 
 
4854
        VBOXVHWACMD_SURF_OVERLAY_UPDATE updateCmd;
 
4855
        memset(&updateCmd, 0, sizeof(updateCmd));
 
4856
        updateCmd.u.in.hSrcSurf = (VBOXVHWA_SURFHANDLE)g_apSurf[0];
 
4857
        updateCmd.u.in.hDstSurf = (VBOXVHWA_SURFHANDLE)pDisplay;
 
4858
        updateCmd.u.in.flags =
 
4859
                VBOXVHWA_OVER_SHOW
 
4860
                | VBOXVHWA_OVER_KEYDESTOVERRIDE;
 
4861
 
 
4862
        updateCmd.u.in.desc.DstCK.high = 1;
 
4863
        updateCmd.u.in.desc.DstCK.low = 1;
 
4864
 
 
4865
        updateCmd.u.in.dstRect.left = 0;
 
4866
        updateCmd.u.in.dstRect.right = pDisplay->width();
 
4867
        updateCmd.u.in.dstRect.top = (pDisplay->height() - height)/2;
 
4868
        updateCmd.u.in.dstRect.bottom = updateCmd.u.in.dstRect.top + height;
 
4869
 
 
4870
        updateCmd.u.in.srcRect.left = 0;
 
4871
        updateCmd.u.in.srcRect.right = width;
 
4872
        updateCmd.u.in.srcRect.top = 0;
 
4873
        updateCmd.u.in.srcRect.bottom = height;
 
4874
 
 
4875
        updateCmd.u.in.offDstSurface = VBOXVHWA_OFFSET64_VOID; /* just a magic to avoid surf mem buffer change  */
 
4876
        updateCmd.u.in.offSrcSurface = VBOXVHWA_OFFSET64_VOID; /* just a magic to avoid surf mem buffer change  */
 
4877
 
 
4878
        vhwaSurfaceOverlayUpdate(&updateCmd);
 
4879
    }
 
4880
#endif
 
4881
 
 
4882
    if(!mOnResizeCmdList.empty())
 
4883
    {
 
4884
        for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin();
 
4885
             it != mOnResizeCmdList.end(); ++ it)
 
4886
        {
 
4887
            VBOXVHWACMD * pCmd = (*it);
 
4888
            vboxDoVHWACmdExec(pCmd);
 
4889
            free(pCmd);
 
4890
        }
 
4891
        mOnResizeCmdList.clear();
 
4892
    }
 
4893
 
 
4894
 
 
4895
//    mDisplay.performDisplay();
 
4896
 
 
4897
    if (remind)
 
4898
    {
 
4899
        class RemindEvent : public VBoxAsyncEvent
 
4900
        {
 
4901
            ulong mRealBPP;
 
4902
        public:
 
4903
            RemindEvent (ulong aRealBPP)
 
4904
                : mRealBPP (aRealBPP) {}
 
4905
            void handle()
 
4906
            {
 
4907
                vboxProblem().remindAboutWrongColorDepth (mRealBPP, 32);
 
4908
            }
 
4909
        };
 
4910
        (new RemindEvent (re->bitsPerPixel()))->post();
 
4911
    }
 
4912
}
 
4913
 
 
4914
VBoxVHWAColorFormat::VBoxVHWAColorFormat(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b) :
 
4915
    mWidthCompression(1),
 
4916
    mHeightCompression(1)
 
4917
{
 
4918
    init(bitsPerPixel, r, g, b);
 
4919
}
 
4920
 
 
4921
VBoxVHWAColorFormat::VBoxVHWAColorFormat(uint32_t fourcc) :
 
4922
    mWidthCompression(1),
 
4923
    mHeightCompression(1)
 
4924
{
 
4925
    init(fourcc);
 
4926
}
 
4927
 
 
4928
void VBoxVHWAColorFormat::init(uint32_t fourcc)
 
4929
{
 
4930
    mDataFormat = fourcc;
 
4931
    mInternalFormat = GL_RGBA8;//GL_RGB;
 
4932
    mFormat = GL_BGRA_EXT;//GL_RGBA;
 
4933
    mType = GL_UNSIGNED_BYTE;
 
4934
    mR = VBoxVHWAColorComponent(0xff);
 
4935
    mG = VBoxVHWAColorComponent(0xff);
 
4936
    mB = VBoxVHWAColorComponent(0xff);
 
4937
    mA = VBoxVHWAColorComponent(0xff);
 
4938
    mBitsPerPixelTex = 32;
 
4939
 
 
4940
    switch(fourcc)
 
4941
    {
 
4942
        case FOURCC_AYUV:
 
4943
            mBitsPerPixel = 32;
 
4944
            mWidthCompression = 1;
 
4945
            break;
 
4946
        case FOURCC_UYVY:
 
4947
        case FOURCC_YUY2:
 
4948
            mBitsPerPixel = 16;
 
4949
            mWidthCompression = 2;
 
4950
            break;
 
4951
        case FOURCC_YV12:
 
4952
            mBitsPerPixel = 8;
 
4953
            mWidthCompression = 4;
 
4954
            break;
 
4955
        default:
 
4956
            Assert(0);
 
4957
            mBitsPerPixel = 0;
 
4958
            mBitsPerPixelTex = 0;
 
4959
            mWidthCompression = 0;
 
4960
            break;
 
4961
    }
 
4962
}
 
4963
 
 
4964
void VBoxVHWAColorFormat::init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
 
4965
{
 
4966
    mBitsPerPixel = bitsPerPixel;
 
4967
    mBitsPerPixelTex = bitsPerPixel;
 
4968
    mDataFormat = 0;
 
4969
    switch (bitsPerPixel)
 
4970
    {
 
4971
        case 32:
 
4972
            mInternalFormat = GL_RGB;//3;//GL_RGB;
 
4973
            mFormat = GL_BGRA_EXT;//GL_RGBA;
 
4974
            mType = GL_UNSIGNED_BYTE;
 
4975
            mR = VBoxVHWAColorComponent(r);
 
4976
            mG = VBoxVHWAColorComponent(g);
 
4977
            mB = VBoxVHWAColorComponent(b);
 
4978
            break;
 
4979
        case 24:
 
4980
#ifdef DEBUG_misha
 
4981
            Assert(0);
 
4982
#endif
 
4983
            mInternalFormat = 3;//GL_RGB;
 
4984
            mFormat = GL_BGR_EXT;
 
4985
            mType = GL_UNSIGNED_BYTE;
 
4986
            mR = VBoxVHWAColorComponent(r);
 
4987
            mG = VBoxVHWAColorComponent(g);
 
4988
            mB = VBoxVHWAColorComponent(b);
 
4989
            break;
 
4990
        case 16:
 
4991
#ifdef DEBUG_misha
 
4992
            Assert(0);
 
4993
#endif
 
4994
            mInternalFormat = GL_RGB5;
 
4995
            mFormat = GL_BGR_EXT;
 
4996
            mType = GL_UNSIGNED_BYTE; /* TODO" ??? */
 
4997
            mR = VBoxVHWAColorComponent(r);
 
4998
            mG = VBoxVHWAColorComponent(g);
 
4999
            mB = VBoxVHWAColorComponent(b);
 
5000
            break;
 
5001
        case 8:
 
5002
#ifdef DEBUG_misha
 
5003
            Assert(0);
 
5004
#endif
 
5005
            mInternalFormat = 1;//GL_RGB;
 
5006
            mFormat = GL_RED;//GL_RGB;
 
5007
            mType = GL_UNSIGNED_BYTE;
 
5008
            mR = VBoxVHWAColorComponent(0xff);
 
5009
            break;
 
5010
        case 1:
 
5011
#ifdef DEBUG_misha
 
5012
            Assert(0);
 
5013
#endif
 
5014
            mInternalFormat = 1;
 
5015
            mFormat = GL_COLOR_INDEX;
 
5016
            mType = GL_BITMAP;
 
5017
            mR = VBoxVHWAColorComponent(0x1);
 
5018
            break;
 
5019
        default:
 
5020
#ifdef DEBUG_misha
 
5021
            Assert(0);
 
5022
#endif
 
5023
            mBitsPerPixel = 0;
 
5024
            mBitsPerPixelTex = 0;
 
5025
            break;
 
5026
    }
 
5027
}
 
5028
 
 
5029
bool VBoxVHWAColorFormat::equals (const VBoxVHWAColorFormat & other) const
 
5030
{
 
5031
    if(fourcc())
 
5032
        return fourcc() == other.fourcc();
 
5033
    if(other.fourcc())
 
5034
        return false;
 
5035
 
 
5036
    return bitsPerPixel() == other.bitsPerPixel();
 
5037
}
 
5038
 
 
5039
VBoxVHWAColorComponent::VBoxVHWAColorComponent(uint32_t aMask)
 
5040
{
 
5041
    unsigned f = ASMBitFirstSetU32(aMask);
 
5042
    if(f)
 
5043
    {
 
5044
        mOffset = f - 1;
 
5045
        f = ASMBitFirstSetU32(~(aMask >> mOffset));
 
5046
        if(f)
 
5047
        {
 
5048
            mcBits = f - 1;
 
5049
        }
 
5050
        else
 
5051
        {
 
5052
            mcBits = 32 - mOffset;
 
5053
        }
 
5054
 
 
5055
        Assert(mcBits);
 
5056
        mMask = (((uint32_t)0xffffffff) >> (32 - mcBits)) << mOffset;
 
5057
        Assert(mMask == aMask);
 
5058
 
 
5059
        mRange = (mMask >> mOffset) + 1;
 
5060
    }
 
5061
    else
 
5062
    {
 
5063
        mMask = 0;
 
5064
        mRange = 0;
 
5065
        mOffset = 32;
 
5066
        mcBits = 0;
 
5067
    }
 
5068
}
 
5069
 
 
5070
void VBoxVHWAColorFormat::pixel2Normalized (uint32_t pix, float *r, float *g, float *b) const
 
5071
{
 
5072
    *r = mR.colorValNorm(pix);
 
5073
    *g = mG.colorValNorm(pix);
 
5074
    *b = mB.colorValNorm(pix);
 
5075
}
 
5076
 
 
5077
VBoxQGLOverlay::VBoxQGLOverlay (VBoxConsoleView *aView, VBoxFrameBuffer * aContainer)
 
5078
    : mpOverlayWidget(NULL),
 
5079
      mView(aView),
 
5080
      mContainer(aContainer),
 
5081
      mGlOn(false),
 
5082
      mOverlayWidgetVisible(false),
 
5083
      mOverlayVisible(false),
 
5084
      mGlCurrent(false),
 
5085
      mProcessingCommands(false),
 
5086
      mNeedOverlayRepaint(false),
 
5087
      mNeedSetVisible(false),
 
5088
      mCmdPipe(aView)
 
5089
{
 
5090
    /* postpone the gl widget initialization to avoid conflict with 3D on Mac */
 
5091
}
 
5092
 
 
5093
void VBoxQGLOverlay::initGl()
 
5094
{
 
5095
        if(mpOverlayWidget)
 
5096
                return;
 
5097
        
 
5098
    mpOverlayWidget = new VBoxGLWidget (mView, mView->viewport());
 
5099
        
 
5100
    VBoxGLContext *pc = (VBoxGLContext*)mpOverlayWidget->context();
 
5101
    pc->allowDoneCurrent(false);
 
5102
        
 
5103
    mOverlayWidgetVisible = true; /* to ensure it is set hidden with vboxShowOverlay */
 
5104
    vboxShowOverlay(false);
 
5105
        
 
5106
    mpOverlayWidget->setMouseTracking(true);
 
5107
}
 
5108
 
 
5109
int VBoxQGLOverlay::reset()
 
5110
{
 
5111
    VBoxVHWACommandElement * pHead, * pTail;
 
5112
    mCmdPipe.reset(&pHead, &pTail);
 
5113
    if(pHead)
 
5114
    {
 
5115
        CDisplay display = mView->console().GetDisplay();
 
5116
        Assert (!display.isNull());
 
5117
 
 
5118
        /* complete aborted commands */
 
5119
        for(VBoxVHWACommandElement * pCur = pHead; pCur; pCur = pCur->mpNext)
 
5120
        {
 
5121
            switch(pCur->type())
 
5122
            {
 
5123
#ifdef VBOX_WITH_VIDEOHWACCEL
 
5124
            case VBOXVHWA_PIPECMD_VHWA:
 
5125
                {
 
5126
                    struct _VBOXVHWACMD * pCmd = pCur->vhwaCmd();
 
5127
                    pCmd->rc = VERR_INVALID_STATE;
 
5128
                    display.CompleteVHWACommand((BYTE*)pCmd);
 
5129
                }
 
5130
                break;
 
5131
            case VBOXVHWA_PIPECMD_OP:
 
5132
                /* should not happen, don't handle this for now */
 
5133
                Assert(0);
 
5134
                break;
 
5135
            case VBOXVHWA_PIPECMD_FUNC:
 
5136
                /* should not happen, don't handle this for now */
 
5137
                Assert(0);
 
5138
                break;
 
5139
#endif
 
5140
            case VBOXVHWA_PIPECMD_PAINT:
 
5141
                break;
 
5142
            default:
 
5143
                /* should not happen, don't handle this for now */
 
5144
                Assert(0);
 
5145
                break;
 
5146
            }
 
5147
        }
 
5148
 
 
5149
        VBoxVHWACommandElement *pTest = mCmdPipe.detachCmdList(pHead, pTail);
 
5150
        Assert(!pTest);
 
5151
        NOREF(pTest);
 
5152
    }
 
5153
 
 
5154
    resetGl();
 
5155
 
 
5156
    return VINF_SUCCESS;
 
5157
}
 
5158
 
 
5159
static DECLCALLBACK(void) vbvaVHWAHHCommandFreeCmd(void * pContext)
 
5160
{
 
5161
    free(pContext);
 
5162
}
 
5163
 
 
5164
int VBoxQGLOverlay::resetGl()
 
5165
{
 
5166
    if(mpOverlayWidget)
 
5167
    {
 
5168
        VHWACommandList list;
 
5169
        int rc = mpOverlayWidget->reset(&list);
 
5170
        if(RT_SUCCESS(rc))
 
5171
        {
 
5172
            for (VHWACommandList::const_iterator sIt = list.begin();
 
5173
                    sIt != list.end(); ++ sIt)
 
5174
            {
 
5175
                VBOXVHWACMD *pCmd = (*sIt);
 
5176
                VBOXVHWA_HH_CALLBACK_SET(pCmd, vbvaVHWAHHCommandFreeCmd, pCmd);
 
5177
                mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, 0);
 
5178
            }
 
5179
        }
 
5180
    }
 
5181
    return VINF_SUCCESS;
 
5182
}
 
5183
 
 
5184
int VBoxQGLOverlay::onVHWACommand(struct _VBOXVHWACMD * pCmd)
 
5185
{
 
5186
    uint32_t flags = 0;
 
5187
    switch(pCmd->enmCmd)
 
5188
    {
 
5189
        case VBOXVHWACMD_TYPE_SURF_FLIP:
 
5190
        case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
 
5191
        case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
 
5192
            flags |= VBOXVHWACMDPIPEC_COMPLETEEVENT;
 
5193
            break;
 
5194
        case VBOXVHWACMD_TYPE_HH_RESET:
 
5195
        {
 
5196
            /* we do not post a reset command to the gui thread since this may lead to a deadlock
 
5197
             * when reset is initiated by the gui thread*/
 
5198
            pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
 
5199
            pCmd->rc = reset();
 
5200
            return VINF_SUCCESS;
 
5201
        }
 
5202
        default:
 
5203
            break;
 
5204
    }//    Assert(0);
 
5205
    /* indicate that we process and complete the command asynchronously */
 
5206
    pCmd->Flags |= VBOXVHWACMD_FLAG_HG_ASYNCH;
 
5207
 
 
5208
    mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, flags);
 
5209
    return VINF_SUCCESS;
 
5210
 
 
5211
}
 
5212
 
 
5213
void VBoxQGLOverlay::onVHWACommandEvent(QEvent * pEvent)
 
5214
{
 
5215
    Q_UNUSED(pEvent);
 
5216
    Assert(!mProcessingCommands);
 
5217
    mProcessingCommands = true;
 
5218
    Assert(!mGlCurrent);
 
5219
    mGlCurrent = false; /* just a fall-back */
 
5220
    VBoxVHWACommandElement * pFirst = mCmdPipe.detachCmdList(NULL, NULL);
 
5221
    while(pFirst) /* pFirst can be zero right after reset when all pending commands are flushed,
 
5222
                   * while events for those commands may still come along */
 
5223
    {
 
5224
        VBoxVHWACommandElement * pLast = processCmdList(pFirst);
 
5225
 
 
5226
        pFirst = mCmdPipe.detachCmdList(pFirst, pLast);
 
5227
    }
 
5228
 
 
5229
    mProcessingCommands = false;
 
5230
    repaint();
 
5231
//    vboxOpExit();
 
5232
    mGlCurrent = false;
 
5233
}
 
5234
 
 
5235
bool VBoxQGLOverlay::onNotifyUpdate(ULONG aX, ULONG aY,
 
5236
                         ULONG aW, ULONG aH)
 
5237
{
 
5238
#if 1
 
5239
    QRect r(aX, aY, aW, aH);
 
5240
    mCmdPipe.postCmd(VBOXVHWA_PIPECMD_PAINT, &r, 0);
 
5241
    return true;
 
5242
#else
 
5243
    /* We're not on the GUI thread and update() isn't thread safe in
 
5244
     * Qt 4.3.x on the Win, Qt 3.3.x on the Mac (4.2.x is),
 
5245
     * on Linux (didn't check Qt 4.x there) and probably on other
 
5246
     * non-DOS platforms, so post the event instead. */
 
5247
    QApplication::postEvent (mView,
 
5248
                             new VBoxRepaintEvent (aX, aY, aW, aH));
 
5249
 
 
5250
    return S_OK;
 
5251
#endif
 
5252
}
 
5253
 
 
5254
//VBOXFBOVERLAY_RESUT VBoxQGLOverlay::onPaintEvent (const QPaintEvent *pe, QRect *pRect)
 
5255
//{
 
5256
//    Q_UNUSED(pe);
 
5257
//    Q_UNUSED(pRect);
 
5258
//
 
5259
////    if(mOverlayWidgetVisible && !mProcessingCommands)
 
5260
////    {
 
5261
////        Assert(!mGlCurrent);
 
5262
////        vboxDoCheckUpdateViewport();
 
5263
////        vboxOpExit();
 
5264
////    }
 
5265
//    return VBOXFBOVERLAY_UNTOUCHED;
 
5266
//}
 
5267
 
 
5268
void VBoxQGLOverlay::onResizeEvent (const VBoxResizeEvent *re)
 
5269
{
 
5270
    Q_UNUSED(re);
 
5271
}
 
5272
 
 
5273
void VBoxQGLOverlay::onResizeEventPostprocess (const VBoxResizeEvent *re)
 
5274
{
 
5275
    Q_UNUSED(re);
 
5276
 
 
5277
    if(mGlOn)
 
5278
    {
 
5279
        Assert(!mGlCurrent);
 
5280
        Assert(!mNeedOverlayRepaint);
 
5281
        mGlCurrent = false;
 
5282
        makeCurrent();
 
5283
        /* need to ensure we're in synch */
 
5284
        mNeedOverlayRepaint = vboxSynchGl();
 
5285
    }
 
5286
 
 
5287
    if(!mOnResizeCmdList.empty())
 
5288
    {
 
5289
        for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin();
 
5290
             it != mOnResizeCmdList.end(); ++ it)
 
5291
        {
 
5292
            VBOXVHWACMD * pCmd = (*it);
 
5293
            vboxDoVHWACmdExec(pCmd);
 
5294
            free(pCmd);
 
5295
        }
 
5296
        mOnResizeCmdList.clear();
 
5297
    }
 
5298
 
 
5299
    repaintOverlay();
 
5300
    mGlCurrent = false;
 
5301
}
 
5302
 
 
5303
void VBoxQGLOverlay::repaintMain()
 
5304
{
 
5305
    if(mMainDirtyRect.isClear())
 
5306
        return;
 
5307
 
 
5308
    const QRect &rect = mMainDirtyRect.rect();
 
5309
    if(mOverlayWidgetVisible)
 
5310
    {
 
5311
        if(mOverlayViewport.contains(rect))
 
5312
            return;
 
5313
    }
 
5314
 
 
5315
    mView->viewport()->repaint (rect.x() - mView->contentsX(),
 
5316
            rect.y() - mView->contentsY(),
 
5317
            rect.width(), rect.height());
 
5318
 
 
5319
    mMainDirtyRect.clear();
 
5320
}
 
5321
 
 
5322
void VBoxQGLOverlay::vboxDoVHWACmd(void *cmd)
 
5323
{
 
5324
    vboxDoVHWACmdExec(cmd);
 
5325
 
 
5326
    CDisplay display = mView->console().GetDisplay();
 
5327
    Assert (!display.isNull());
 
5328
 
 
5329
    display.CompleteVHWACommand((BYTE*)cmd);
 
5330
}
 
5331
 
 
5332
//void VBoxQGLOverlay::vboxDoUpdateRect(const QRect * pRect)
 
5333
//{
 
5334
//    if(mGlOn)
 
5335
//    {
 
5336
//        makeCurrent();
 
5337
//        mpOverlayWidget->vboxDoUpdateRect(pRect);
 
5338
//        vboxOpExit();
 
5339
//    }
 
5340
//
 
5341
//    mView->viewport()->repaint (pRect->x() - mView->contentsX(),
 
5342
//            pRect->y() - mView->contentsY(),
 
5343
//            pRect->width(), pRect->height());
 
5344
//
 
5345
//    /* translate to widget coords
 
5346
//     * @todo: may eliminate this */
 
5347
////    QPaintEvent pe(pRect->translated(-mView->contentsX(), -mView->contentsY()));
 
5348
////    VBoxQImageFrameBuffer::paintEvent (&pe);
 
5349
//}
 
5350
 
 
5351
bool VBoxQGLOverlay::vboxSynchGl()
 
5352
{
 
5353
    if(mpOverlayWidget->vboxIsInitialized()
 
5354
            && mContainer->pixelFormat() == mpOverlayWidget->vboxPixelFormat()
 
5355
            && mContainer->address() == mpOverlayWidget->vboxAddress()
 
5356
            && mContainer->bitsPerPixel() == mpOverlayWidget->vboxBitsPerPixel()
 
5357
            && mContainer->bytesPerLine() == mpOverlayWidget->vboxBytesPerLine()
 
5358
            && (int)mContainer->width() == mpOverlayWidget->vboxFbWidth()
 
5359
            && (int)mContainer->height() == mpOverlayWidget->vboxFbHeight())
 
5360
    {
 
5361
        return false;
 
5362
    }
 
5363
    /* create and issue a resize event to the gl widget to ensure we have all gl data initialized
 
5364
     * and synchronized with the framebuffer */
 
5365
    VBoxResizeEvent re(mContainer->pixelFormat(),
 
5366
            mContainer->address(),
 
5367
            mContainer->bitsPerPixel(),
 
5368
            mContainer->bytesPerLine(),
 
5369
            mContainer->width(),
 
5370
            mContainer->height());
 
5371
 
 
5372
    mpOverlayWidget->vboxDoResize(&re);
 
5373
    return true;
 
5374
}
 
5375
 
 
5376
void VBoxQGLOverlay::vboxSetGlOn(bool on)
 
5377
{
 
5378
    if(on == mGlOn)
 
5379
        return;
 
5380
 
 
5381
    mGlOn = on;
 
5382
 
 
5383
    if(on)
 
5384
    {
 
5385
        /* need to ensure we have gl functions initialized */
 
5386
        mpOverlayWidget->makeCurrent();
 
5387
        vboxVHWAGetSupportInfo(mpOverlayWidget->context());
 
5388
 
 
5389
        VBOXQGLLOGREL(("Switching Gl mode on\n"));
 
5390
        Assert(!mpOverlayWidget->isVisible());
 
5391
        /* just to ensure */
 
5392
        vboxShowOverlay(false);
 
5393
        mOverlayVisible = false;
 
5394
        vboxSynchGl();
 
5395
    }
 
5396
    else
 
5397
    {
 
5398
        VBOXQGLLOGREL(("Switching Gl mode off\n"));
 
5399
        mOverlayVisible = false;
 
5400
        vboxShowOverlay(false);
 
5401
        /* for now just set the flag w/o destroying anything */
 
5402
    }
 
5403
}
 
5404
 
 
5405
void VBoxQGLOverlay::vboxDoCheckUpdateViewport()
 
5406
{
 
5407
    if(!mOverlayVisible)
 
5408
    {
 
5409
        vboxShowOverlay(false);
 
5410
        return;
 
5411
    }
 
5412
 
 
5413
    int cX = mView->contentsX();
 
5414
    int cY = mView->contentsY();
 
5415
    QRect fbVp(cX, cY, mView->viewport()->width(), mView->viewport()->height());
 
5416
    QRect overVp = fbVp.intersected(mOverlayViewport);
 
5417
 
 
5418
    if(overVp.isEmpty())
 
5419
    {
 
5420
        vboxShowOverlay(false);
 
5421
    }
 
5422
    else
 
5423
    {
 
5424
        if(overVp != mpOverlayWidget->vboxViewport())
 
5425
        {
 
5426
            makeCurrent();
 
5427
            mpOverlayWidget->vboxDoUpdateViewport(overVp);
 
5428
            mNeedOverlayRepaint = true;
 
5429
        }
 
5430
 
 
5431
        QRect rect(overVp.x() - cX, overVp.y() - cY, overVp.width(), overVp.height());
 
5432
 
 
5433
        vboxCheckUpdateOverlay(rect);
 
5434
 
 
5435
        vboxShowOverlay(true);
 
5436
 
 
5437
        /* workaround for linux ATI issue: need to update gl viewport after widget becomes visible */
 
5438
        mpOverlayWidget->vboxDoUpdateViewport(overVp);
 
5439
    }
 
5440
}
 
5441
 
 
5442
void VBoxQGLOverlay::vboxShowOverlay(bool show)
 
5443
{
 
5444
    if(mOverlayWidgetVisible != show)
 
5445
    {
 
5446
        mpOverlayWidget->setVisible(show);
 
5447
        mOverlayWidgetVisible = show;
 
5448
        mGlCurrent = false;
 
5449
        if(!show)
 
5450
        {
 
5451
            mMainDirtyRect.add(mpOverlayWidget->vboxViewport());
 
5452
        }
 
5453
    }
 
5454
}
 
5455
 
 
5456
//void VBoxQGLOverlayFrameBuffer::vboxUpdateOverlayPosition(const QPoint & pos)
 
5457
//{
 
5458
////    makeCurrent();
 
5459
//
 
5460
//    mpOverlayWidget->move(pos);
 
5461
//
 
5462
////    /* */
 
5463
////    QRect rect = mpOverlayWidget->vboxViewport();
 
5464
////    rect.moveTo(pos);
 
5465
////    mpOverlayWidget->vboxDoUpdateViewport(rect);
 
5466
//}
 
5467
 
 
5468
void VBoxQGLOverlay::vboxCheckUpdateOverlay(const QRect & rect)
 
5469
{
 
5470
    QRect overRect(mpOverlayWidget->pos(), mpOverlayWidget->size());
 
5471
    if(overRect.x() != rect.x() || overRect.y() != rect.y())
 
5472
    {
 
5473
#if defined(RT_OS_WINDOWS)
 
5474
        mpOverlayWidget->setVisible(false);
 
5475
        mNeedSetVisible = true;
 
5476
#endif
 
5477
        VBOXQGLLOG_QRECT("moving wgt to " , &rect, "\n");
 
5478
        mpOverlayWidget->move(rect.x(), rect.y());
 
5479
        mGlCurrent = false;
 
5480
    }
 
5481
 
 
5482
    if(overRect.width() != rect.width() || overRect.height() != rect.height())
 
5483
    {
 
5484
#if defined(RT_OS_WINDOWS)
 
5485
        mpOverlayWidget->setVisible(false);
 
5486
        mNeedSetVisible = true;
 
5487
#endif
 
5488
        VBOXQGLLOG(("resizing wgt to w(%d) ,h(%d)\n" , rect.width(), rect.height()));
 
5489
        mpOverlayWidget->resize(rect.width(), rect.height());
 
5490
        mGlCurrent = false;
 
5491
    }
 
5492
 
 
5493
//    mpOverlayWidget->vboxDoUpdateViewport(rect);
 
5494
//
 
5495
//    vboxShowOverlay(show);
 
5496
}
 
5497
 
 
5498
void VBoxQGLOverlay::addMainDirtyRect(const QRect & aRect)
 
5499
{
 
5500
    mMainDirtyRect.add(aRect);
 
5501
    if(mGlOn)
 
5502
    {
 
5503
        mpOverlayWidget->vboxDoUpdateRect(&aRect);
 
5504
        mNeedOverlayRepaint = true;
 
5505
    }
 
5506
}
 
5507
 
 
5508
int VBoxQGLOverlay::vhwaSurfaceUnlock(struct _VBOXVHWACMD_SURF_UNLOCK *pCmd)
 
5509
{
 
5510
    int rc = mpOverlayWidget->vhwaSurfaceUnlock(pCmd);
 
5511
    VBoxVHWASurfaceBase * pVGA = mpOverlayWidget->vboxGetVGASurface();
 
5512
    const VBoxVHWADirtyRect & rect = pVGA->getDirtyRect();
 
5513
    mNeedOverlayRepaint = true;
 
5514
    if(!rect.isClear())
 
5515
    {
 
5516
        mMainDirtyRect.add(rect);
 
5517
    }
 
5518
    return rc;
 
5519
}
 
5520
 
 
5521
void VBoxQGLOverlay::vboxDoVHWACmdExec(void *cmd)
 
5522
{
 
5523
    struct _VBOXVHWACMD * pCmd = (struct _VBOXVHWACMD *)cmd;
 
5524
    switch(pCmd->enmCmd)
 
5525
    {
 
5526
        case VBOXVHWACMD_TYPE_SURF_CANCREATE:
 
5527
        {
 
5528
            VBOXVHWACMD_SURF_CANCREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CANCREATE);
 
5529
            makeCurrent();
 
5530
            pCmd->rc = mpOverlayWidget->vhwaSurfaceCanCreate(pBody);
 
5531
        } break;
 
5532
        case VBOXVHWACMD_TYPE_SURF_CREATE:
 
5533
        {
 
5534
            VBOXVHWACMD_SURF_CREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
 
5535
            makeCurrent();
 
5536
            vboxSetGlOn(true);
 
5537
            pCmd->rc = mpOverlayWidget->vhwaSurfaceCreate(pBody);
 
5538
            if(!mpOverlayWidget->hasSurfaces())
 
5539
            {
 
5540
                vboxSetGlOn(false);
 
5541
            }
 
5542
            else
 
5543
            {
 
5544
                mOverlayVisible = mpOverlayWidget->hasVisibleOverlays();
 
5545
                if(mOverlayVisible)
 
5546
                {
 
5547
                    mOverlayViewport = mpOverlayWidget->overlaysRectUnion();
 
5548
                }
 
5549
                vboxDoCheckUpdateViewport();
 
5550
                mNeedOverlayRepaint = true;
 
5551
            }
 
5552
        } break;
 
5553
        case VBOXVHWACMD_TYPE_SURF_DESTROY:
 
5554
        {
 
5555
            VBOXVHWACMD_SURF_DESTROY * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
 
5556
            makeCurrent();
 
5557
            pCmd->rc = mpOverlayWidget->vhwaSurfaceDestroy(pBody);
 
5558
            if(!mpOverlayWidget->hasSurfaces())
 
5559
            {
 
5560
                vboxSetGlOn(false);
 
5561
            }
 
5562
            else
 
5563
            {
 
5564
                mOverlayVisible = mpOverlayWidget->hasVisibleOverlays();
 
5565
                if(mOverlayVisible)
 
5566
                {
 
5567
                    mOverlayViewport = mpOverlayWidget->overlaysRectUnion();
 
5568
                }
 
5569
                vboxDoCheckUpdateViewport();
 
5570
                mNeedOverlayRepaint = true;
 
5571
            }
 
5572
        } break;
 
5573
        case VBOXVHWACMD_TYPE_SURF_LOCK:
 
5574
        {
 
5575
            VBOXVHWACMD_SURF_LOCK * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
 
5576
            makeCurrent();
 
5577
            pCmd->rc = mpOverlayWidget->vhwaSurfaceLock(pBody);
 
5578
        } break;
 
5579
        case VBOXVHWACMD_TYPE_SURF_UNLOCK:
 
5580
        {
 
5581
            VBOXVHWACMD_SURF_UNLOCK * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_UNLOCK);
 
5582
            makeCurrent();
 
5583
            pCmd->rc = vhwaSurfaceUnlock(pBody);
 
5584
            /* mNeedOverlayRepaint is set inside the vhwaSurfaceUnlock */
 
5585
        } break;
 
5586
        case VBOXVHWACMD_TYPE_SURF_BLT:
 
5587
        {
 
5588
            VBOXVHWACMD_SURF_BLT * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
 
5589
            makeCurrent();
 
5590
            pCmd->rc = mpOverlayWidget->vhwaSurfaceBlt(pBody);
 
5591
            mNeedOverlayRepaint = true;
 
5592
        } break;
 
5593
        case VBOXVHWACMD_TYPE_SURF_FLIP:
 
5594
        {
 
5595
            VBOXVHWACMD_SURF_FLIP * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
 
5596
            makeCurrent();
 
5597
            pCmd->rc = mpOverlayWidget->vhwaSurfaceFlip(pBody);
 
5598
            mNeedOverlayRepaint = true;
 
5599
        } break;
 
5600
        case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
 
5601
        {
 
5602
            VBOXVHWACMD_SURF_OVERLAY_UPDATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
 
5603
            makeCurrent();
 
5604
            pCmd->rc = mpOverlayWidget->vhwaSurfaceOverlayUpdate(pBody);
 
5605
            mOverlayVisible = mpOverlayWidget->hasVisibleOverlays();
 
5606
            if(mOverlayVisible)
 
5607
            {
 
5608
                mOverlayViewport = mpOverlayWidget->overlaysRectUnion();
 
5609
            }
 
5610
            vboxDoCheckUpdateViewport();
 
5611
            mNeedOverlayRepaint = true;
 
5612
        } break;
 
5613
        case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
 
5614
        {
 
5615
            VBOXVHWACMD_SURF_OVERLAY_SETPOSITION * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_SETPOSITION);
 
5616
            makeCurrent();
 
5617
            pCmd->rc = mpOverlayWidget->vhwaSurfaceOverlaySetPosition(pBody);
 
5618
            mOverlayVisible = mpOverlayWidget->hasVisibleOverlays();
 
5619
            if(mOverlayVisible)
 
5620
            {
 
5621
                mOverlayViewport = mpOverlayWidget->overlaysRectUnion();
 
5622
            }
 
5623
            vboxDoCheckUpdateViewport();
 
5624
            mNeedOverlayRepaint = true;
 
5625
        } break;
 
5626
        case VBOXVHWACMD_TYPE_SURF_COLORKEY_SET:
 
5627
        {
 
5628
            VBOXVHWACMD_SURF_COLORKEY_SET * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORKEY_SET);
 
5629
            makeCurrent();
 
5630
            pCmd->rc = mpOverlayWidget->vhwaSurfaceColorkeySet(pBody);
 
5631
            /* this is here to ensure we have color key changes picked up */
 
5632
            vboxDoCheckUpdateViewport();
 
5633
            mNeedOverlayRepaint = true;
 
5634
        } break;
 
5635
        case VBOXVHWACMD_TYPE_QUERY_INFO1:
 
5636
        {
 
5637
            VBOXVHWACMD_QUERYINFO1 * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
 
5638
            initGl();
 
5639
            makeCurrent();
 
5640
            pCmd->rc = mpOverlayWidget->vhwaQueryInfo1(pBody);
 
5641
        } break;
 
5642
        case VBOXVHWACMD_TYPE_QUERY_INFO2:
 
5643
        {
 
5644
            VBOXVHWACMD_QUERYINFO2 * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
 
5645
            makeCurrent();
 
5646
            pCmd->rc = mpOverlayWidget->vhwaQueryInfo2(pBody);
 
5647
        } break;
 
5648
        case VBOXVHWACMD_TYPE_ENABLE:
 
5649
                        initGl();
 
5650
        case VBOXVHWACMD_TYPE_DISABLE:
 
5651
            pCmd->rc = VINF_SUCCESS;
 
5652
            break;
 
5653
        case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
 
5654
        {
 
5655
            VBOXVHWACMD_HH_CONSTRUCT * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
 
5656
            pCmd->rc = vhwaConstruct(pBody);
 
5657
        } break;
 
5658
        default:
 
5659
            Assert(0);
 
5660
            pCmd->rc = VERR_NOT_IMPLEMENTED;
 
5661
            break;
 
5662
    }
 
5663
}
 
5664
 
 
5665
static DECLCALLBACK(void) vboxQGLOverlaySaveExec(PSSMHANDLE pSSM, void *pvUser)
 
5666
{
 
5667
    VBoxQGLOverlay * fb = (VBoxQGLOverlay*)pvUser;
 
5668
    fb->vhwaSaveExec(pSSM);
 
5669
}
 
5670
 
 
5671
static DECLCALLBACK(int) vboxQGLOverlayLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
 
5672
{
 
5673
    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
 
5674
    VBoxQGLOverlay * fb = (VBoxQGLOverlay*)pvUser;
 
5675
    return fb->vhwaLoadExec(pSSM, u32Version);
 
5676
}
 
5677
 
 
5678
int VBoxQGLOverlay::vhwaLoadExec(struct SSMHANDLE * pSSM, uint32_t u32Version)
 
5679
{
 
5680
//    bool bTmp;
 
5681
//    int rc = SSMR3GetBool(pSSM, &bTmp /*&mGlOn*/);         AssertRC(rc);
 
5682
//    rc = SSMR3GetBool(pSSM, &bTmp /*&mOverlayVisible*/);         AssertRC(rc);
 
5683
//    if(RT_SUCCESS(rc))
 
5684
    return VBoxGLWidget::vhwaLoadExec(&mOnResizeCmdList, pSSM, u32Version);
 
5685
//    return rc;
 
5686
}
 
5687
 
 
5688
void VBoxQGLOverlay::vhwaSaveExec(struct SSMHANDLE * pSSM)
 
5689
{
 
5690
//    int rc = SSMR3PutBool(pSSM, mGlOn);         AssertRC(rc);
 
5691
//    rc = SSMR3PutBool(pSSM, mOverlayVisible);         AssertRC(rc);
 
5692
//
 
5693
    if(mpOverlayWidget)
 
5694
        mpOverlayWidget->vhwaSaveExec(pSSM);
 
5695
    else
 
5696
        VBoxGLWidget::vhwaSaveExecVoid(pSSM);
 
5697
}
 
5698
 
 
5699
int VBoxQGLOverlay::vhwaConstruct(struct _VBOXVHWACMD_HH_CONSTRUCT *pCmd)
 
5700
{
 
5701
    PVM pVM = (PVM)pCmd->pVM;
 
5702
    uint32_t intsId = 0; /* @todo: set the proper id */
 
5703
 
 
5704
    char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
 
5705
 
 
5706
    char * pszName = nameFuf;
 
5707
    sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
 
5708
    int rc = SSMR3RegisterExternal(
 
5709
            pVM,                    /* The VM handle*/
 
5710
            pszName,                /* Data unit name. */
 
5711
            intsId,                 /* The instance identifier of the data unit.
 
5712
                                     * This must together with the name be unique. */
 
5713
            VBOXQGL_STATE_VERSION,   /* Data layout version number. */
 
5714
            128,             /* The approximate amount of data in the unit.
 
5715
                              * Only for progress indicators. */
 
5716
            NULL, NULL, NULL, /* pfnLiveXxx */
 
5717
            NULL,            /* Prepare save callback, optional. */
 
5718
            vboxQGLOverlaySaveExec, /* Execute save callback, optional. */
 
5719
            NULL,            /* Done save callback, optional. */
 
5720
            NULL,            /* Prepare load callback, optional. */
 
5721
            vboxQGLOverlayLoadExec, /* Execute load callback, optional. */
 
5722
            NULL,            /* Done load callback, optional. */
 
5723
            this             /* User argument. */
 
5724
            );
 
5725
    Assert(RT_SUCCESS(rc));
 
5726
    return rc;
 
5727
}
 
5728
 
 
5729
/* static */
 
5730
bool VBoxQGLOverlay::isAcceleration2DVideoAvailable()
 
5731
{
 
5732
#ifndef DEBUG_misha
 
5733
    if(!g_bVBoxVHWAChecked)
 
5734
#endif
 
5735
    {
 
5736
        g_bVBoxVHWAChecked = true;
 
5737
        g_bVBoxVHWASupported = VBoxVHWAInfo::checkVHWASupport();
 
5738
    }
 
5739
    return g_bVBoxVHWASupported;
 
5740
}
 
5741
 
 
5742
/** additional video memory required for the best 2D support performance
 
5743
 *  total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory  */
 
5744
/* static */
 
5745
quint64 VBoxQGLOverlay::required2DOffscreenVideoMemory()
 
5746
{
 
5747
    /* HDTV == 1920x1080 ~ 2M
 
5748
     * for the 4:2:2 formats each pixel is 2Bytes
 
5749
     * so each frame may be 4MB
 
5750
     * so for triple-buffering we would need 12 MB */
 
5751
    return _1M * 12;
 
5752
}
 
5753
 
 
5754
VBoxVHWACommandElement * VBoxQGLOverlay::processCmdList(VBoxVHWACommandElement * pCmd)
 
5755
{
 
5756
    VBoxVHWACommandElement * pCur;
 
5757
    do
 
5758
    {
 
5759
        pCur = pCmd;
 
5760
        switch(pCmd->type())
 
5761
        {
 
5762
        case VBOXVHWA_PIPECMD_PAINT:
 
5763
            addMainDirtyRect(pCmd->rect());
 
5764
            break;
 
5765
#ifdef VBOX_WITH_VIDEOHWACCEL
 
5766
        case VBOXVHWA_PIPECMD_VHWA:
 
5767
            vboxDoVHWACmd(pCmd->vhwaCmd());
 
5768
            break;
 
5769
        case VBOXVHWA_PIPECMD_OP:
 
5770
        {
 
5771
            const VBOXVHWACALLBACKINFO & info = pCmd->op();
 
5772
            (info.pThis->*(info.pfnCallback))(info.pContext);
 
5773
            break;
 
5774
        }
 
5775
        case VBOXVHWA_PIPECMD_FUNC:
 
5776
        {
 
5777
            const VBOXVHWAFUNCCALLBACKINFO & info = pCmd->func();
 
5778
            info.pfnCallback(info.pContext1, info.pContext2);
 
5779
            break;
 
5780
        }
 
5781
#endif
 
5782
        default:
 
5783
            Assert(0);
 
5784
        }
 
5785
        pCmd = pCmd->mpNext;
 
5786
    } while(pCmd);
 
5787
 
 
5788
    return pCur;
 
5789
}
 
5790
 
 
5791
 
 
5792
VBoxVHWACommandElementProcessor::VBoxVHWACommandElementProcessor(VBoxConsoleView *aView) :
 
5793
    mpFirstEvent (NULL),
 
5794
    mpLastEvent (NULL),
 
5795
    mbNewEvent (false),
 
5796
    mbProcessingList (false)
 
5797
{
 
5798
    int rc = RTCritSectInit(&mCritSect);
 
5799
    AssertRC(rc);
 
5800
 
 
5801
    mView = aView;
 
5802
 
 
5803
    for(int i = RT_ELEMENTS(mElementsBuffer) - 1; i >= 0; i--)
 
5804
    {
 
5805
        mFreeElements.push(&mElementsBuffer[i]);
 
5806
    }
 
5807
}
 
5808
 
 
5809
VBoxVHWACommandElementProcessor::~VBoxVHWACommandElementProcessor()
 
5810
{
 
5811
    RTCritSectDelete(&mCritSect);
 
5812
}
 
5813
 
 
5814
void VBoxVHWACommandElementProcessor::completeCurrentEvent()
 
5815
{
 
5816
    RTCritSectEnter(&mCritSect);
 
5817
    mbNewEvent = true;
 
5818
    RTCritSectLeave(&mCritSect);
 
5819
}
 
5820
 
 
5821
void VBoxVHWACommandElementProcessor::postCmd(VBOXVHWA_PIPECMD_TYPE aType, void * pvData, uint32_t flags)
 
5822
{
 
5823
    /* 1. lock*/
 
5824
    RTCritSectEnter(&mCritSect);
 
5825
    VBoxVHWACommandElement * pCmd = mFreeElements.pop();
 
5826
    if(!pCmd)
 
5827
    {
 
5828
        VBOXQGLLOG(("!!!no more free elements!!!\n"));
 
5829
#ifdef VBOXQGL_PROF_BASE
 
5830
        RTCritSectLeave(&mCritSect);
 
5831
        return;
 
5832
#else
 
5833
    //TODO:
 
5834
#endif
 
5835
    }
 
5836
    pCmd->setData(aType, pvData);
 
5837
 
 
5838
    if((flags & VBOXVHWACMDPIPEC_NEWEVENT) != 0)
 
5839
    {
 
5840
        mbNewEvent = true;
 
5841
    }
 
5842
 
 
5843
    /* 2. if can add to current*/
 
5844
    if(!mbNewEvent)
 
5845
    {
 
5846
        /* 3. if event is being processed (event != 0) */
 
5847
        if(mpLastEvent)
 
5848
        {
 
5849
            /* 3.a add cmd to event */
 
5850
            mpLastEvent->pipe().put(pCmd);
 
5851
            /* 3.b unlock and return */
 
5852
            if((flags & VBOXVHWACMDPIPEC_COMPLETEEVENT) != 0)
 
5853
            {
 
5854
                mbNewEvent = true;
 
5855
            }
 
5856
            RTCritSectLeave(&mCritSect);
 
5857
            return;
 
5858
        }
 
5859
    }
 
5860
 
 
5861
    /* we're here because the cmd was NOT be added to the current event queue */
 
5862
    /* 4. unlock*/
 
5863
    RTCritSectLeave(&mCritSect);
 
5864
    /* 5. create & initialize new Event */
 
5865
    VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent(pCmd);
 
5866
    pCurrentEvent->mpNext = NULL;
 
5867
 
 
5868
    /* 6. lock */
 
5869
    RTCritSectEnter(&mCritSect);
 
5870
    /* 7. if no current event set event as current */
 
5871
    if(!mpLastEvent)
 
5872
    {
 
5873
        Assert(!mpFirstEvent);
 
5874
        mpFirstEvent = pCurrentEvent;
 
5875
        mpLastEvent = pCurrentEvent;
 
5876
    }
 
5877
    else
 
5878
    {
 
5879
        mpLastEvent->mpNext = pCurrentEvent;
 
5880
        mpLastEvent = pCurrentEvent;
 
5881
    }
 
5882
    /* 8. reset blocking events counter */
 
5883
    mbNewEvent = ((flags & VBOXVHWACMDPIPEC_COMPLETEEVENT) != 0);
 
5884
    /* 9. unlock */
 
5885
    RTCritSectLeave(&mCritSect);
 
5886
    /* 10. post event */
 
5887
    QApplication::postEvent (mView, pCurrentEvent);
 
5888
}
 
5889
 
 
5890
VBoxVHWACommandElement * VBoxVHWACommandElementProcessor::detachCmdList(VBoxVHWACommandElement * pFirst2Free, VBoxVHWACommandElement * pLast2Free)
 
5891
{
 
5892
    VBoxVHWACommandElement * pList = NULL;
 
5893
    RTCritSectEnter(&mCritSect);
 
5894
    if(pFirst2Free)
 
5895
    {
 
5896
        mFreeElements.pusha(pFirst2Free, pLast2Free);
 
5897
    }
 
5898
    if(mpFirstEvent)
 
5899
    {
 
5900
        pList = mpFirstEvent->pipe().detachList();
 
5901
        if(pList)
 
5902
        {
 
5903
            /* assume the caller atimically calls detachCmdList to free the elements obtained now those and reset the state */
 
5904
            mbProcessingList = true;
 
5905
            RTCritSectLeave(&mCritSect);
 
5906
            return pList;
 
5907
        }
 
5908
        else
 
5909
        {
 
5910
            VBoxVHWACommandProcessEvent *pNext = mpFirstEvent->mpNext;
 
5911
            if(pNext)
 
5912
            {
 
5913
                mpFirstEvent = pNext;
 
5914
            }
 
5915
            else
 
5916
            {
 
5917
                mpFirstEvent = NULL;
 
5918
                mpLastEvent = NULL;
 
5919
            }
 
5920
        }
 
5921
    }
 
5922
 
 
5923
    /* assume the caller atimically calls detachCmdList to free the elements obtained now those and reset the state */
 
5924
    mbProcessingList = false;
 
5925
    RTCritSectLeave(&mCritSect);
 
5926
    return NULL;
 
5927
}
 
5928
 
 
5929
/* it is currently assumed no one sends any new commands while reset is in progress */
 
5930
void VBoxVHWACommandElementProcessor::reset(VBoxVHWACommandElement ** ppHead, VBoxVHWACommandElement ** ppTail)
 
5931
{
 
5932
    VBoxVHWACommandElement * pHead = NULL;
 
5933
    VBoxVHWACommandElement * pTail = NULL;
 
5934
    VBoxVHWACommandProcessEvent * pFirst;
 
5935
    VBoxVHWACommandProcessEvent * pLast;
 
5936
    RTCritSectEnter(&mCritSect);
 
5937
    pFirst = mpFirstEvent;
 
5938
    pLast = mpLastEvent;
 
5939
    mpFirstEvent = NULL;
 
5940
    mpLastEvent = NULL;
 
5941
 
 
5942
    if(mbProcessingList)
 
5943
    {
 
5944
        for(;;)
 
5945
        {
 
5946
            RTCritSectLeave(&mCritSect);
 
5947
            RTThreadSleep(2000); /* 2 ms */
 
5948
            RTCritSectEnter(&mCritSect);
 
5949
            /* it is assumed no one sends any new commands while reset is in progress */
 
5950
            Assert(!mpFirstEvent);
 
5951
            Assert(!mpLastEvent);
 
5952
            if(!mbProcessingList)
 
5953
            {
 
5954
                break;
 
5955
            }
 
5956
        }
 
5957
    }
 
5958
 
 
5959
    if(pFirst)
 
5960
    {
 
5961
        Assert(pLast);
 
5962
        VBoxVHWACommandElement * pCurHead;
 
5963
        for(VBoxVHWACommandProcessEvent * pCur = pFirst; pCur ; pCur = pCur->mpNext)
 
5964
        {
 
5965
            pCurHead = pCur->pipe().detachList();
 
5966
            if(!pCurHead)
 
5967
                continue;
 
5968
            if(!pHead)
 
5969
                pHead = pCurHead;
 
5970
            if(pTail)
 
5971
                pTail->mpNext = pCurHead;
 
5972
 
 
5973
            for(VBoxVHWACommandElement * pCurEl = pCurHead; pCurEl; pCurEl = pCurEl->mpNext)
 
5974
            {
 
5975
                pTail = pCurEl;
 
5976
            }
 
5977
        }
 
5978
 
 
5979
        if(!pTail)
 
5980
            pTail = pHead;
 
5981
    }
 
5982
 
 
5983
    if(pHead)
 
5984
        mbProcessingList = true;
 
5985
 
 
5986
    RTCritSectLeave(&mCritSect);
 
5987
 
 
5988
    *ppHead = pHead;
 
5989
    *ppTail = pTail;
 
5990
}
 
5991
 
 
5992
void VBoxVHWACommandsQueue::enqueue(PFNVBOXQGLFUNC pfn, void* pContext1, void* pContext2)
 
5993
{
 
5994
    VBoxVHWACommandElement *pCmd = new VBoxVHWACommandElement();
 
5995
    VBOXVHWAFUNCCALLBACKINFO info;
 
5996
    info.pfnCallback = pfn;
 
5997
    info.pContext1 = pContext1;
 
5998
    info.pContext2 = pContext2;
 
5999
    pCmd->setFunc(info);
 
6000
    mCmds.put(pCmd);
 
6001
}
 
6002
 
 
6003
VBoxVHWACommandElement * VBoxVHWACommandsQueue::detachList()
 
6004
{
 
6005
    return mCmds.detachList();
 
6006
}
 
6007
 
 
6008
void VBoxVHWACommandsQueue::freeList(VBoxVHWACommandElement * pList)
 
6009
{
 
6010
    while(pList)
 
6011
    {
 
6012
        VBoxVHWACommandElement * pCur = pList;
 
6013
        pList = pCur->mpNext;
 
6014
        delete pCur;
 
6015
    }
 
6016
}
 
6017
 
 
6018
#endif