VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBQGL.cpp@ 22798

Last change on this file since 22798 was 22798, checked in by vboxsync, 15 years ago

video hw accel: bugfixing for using ogl only when needed

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette