VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-ogl.cpp@ 103914

Last change on this file since 103914 was 99775, checked in by vboxsync, 17 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 309.7 KB
Line 
1/* $Id: DevVGA-SVGA3d-ogl.cpp 99775 2023-05-12 12:21:58Z vboxsync $ */
2/** @file
3 * DevVMWare - VMWare SVGA device
4 */
5
6/*
7 * Copyright (C) 2013-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32/* Enable to disassemble defined shaders. (Windows host only) */
33#if defined(RT_OS_WINDOWS) && defined(DEBUG) && 0 /* Disabled as we don't have the DirectX SDK avaible atm. */
34# define DUMP_SHADER_DISASSEMBLY
35#endif
36#ifdef DEBUG_bird
37//# define RTMEM_WRAP_TO_EF_APIS
38#endif
39#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
40#define GL_SILENCE_DEPRECATION /* shut up deprecated warnings on darwin (10.15 sdk) */
41#include <VBox/vmm/pdmdev.h>
42#include <VBox/version.h>
43#include <VBox/err.h>
44#include <VBox/log.h>
45#include <VBox/vmm/pgm.h>
46#include <VBox/AssertGuest.h>
47
48#include <iprt/assert.h>
49#include <iprt/semaphore.h>
50#include <iprt/uuid.h>
51#include <iprt/mem.h>
52
53#include <VBoxVideo.h> /* required by DevVGA.h */
54#include <VBoxVideo3D.h>
55
56/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
57#include "DevVGA.h"
58
59#include "DevVGA-SVGA.h"
60#include "DevVGA-SVGA3d.h"
61#include "DevVGA-SVGA3d-internal.h"
62
63#ifdef DUMP_SHADER_DISASSEMBLY
64# include <d3dx9shader.h>
65#endif
66
67#include <stdlib.h>
68#include <math.h>
69#include <float.h> /* FLT_MIN */
70
71
72/*********************************************************************************************************************************
73* Defined Constants And Macros *
74*********************************************************************************************************************************/
75#ifndef VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE
76# define VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE 1.0
77#endif
78
79#ifdef VMSVGA3D_DYNAMIC_LOAD
80# define OGLGETPROCADDRESS glLdrGetProcAddress
81#else
82#ifdef RT_OS_WINDOWS
83# define OGLGETPROCADDRESS MyWinGetProcAddress
84DECLINLINE(PROC) MyWinGetProcAddress(const char *pszSymbol)
85{
86 /* Khronos: [on failure] "some implementations will return other values. 1, 2, and 3 are used, as well as -1". */
87 PROC p = wglGetProcAddress(pszSymbol);
88 if (RT_VALID_PTR(p))
89 return p;
90 return 0;
91}
92#elif defined(RT_OS_DARWIN)
93# include <dlfcn.h>
94# define OGLGETPROCADDRESS MyNSGLGetProcAddress
95/** Resolves an OpenGL symbol. */
96static void *MyNSGLGetProcAddress(const char *pszSymbol)
97{
98 /* Another copy in shaderapi.c. */
99 static void *s_pvImage = NULL;
100 if (s_pvImage == NULL)
101 s_pvImage = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
102 return s_pvImage ? dlsym(s_pvImage, pszSymbol) : NULL;
103}
104
105#else
106# define OGLGETPROCADDRESS(x) glXGetProcAddress((const GLubyte *)x)
107#endif
108#endif
109
110/* Invert y-coordinate for OpenGL's bottom left origin. */
111#define D3D_TO_OGL_Y_COORD(ptrSurface, y_coordinate) (ptrSurface->paMipmapLevels[0].mipmapSize.height - (y_coordinate))
112#define D3D_TO_OGL_Y_COORD_MIPLEVEL(ptrMipLevel, y_coordinate) (ptrMipLevel->size.height - (y_coordinate))
113
114/**
115 * Macro for doing something and then checking for errors during initialization.
116 * Uses AssertLogRelMsg.
117 */
118#define VMSVGA3D_INIT_CHECKED(a_Expr) \
119 do \
120 { \
121 a_Expr; \
122 GLenum iGlError = glGetError(); \
123 AssertLogRelMsg(iGlError == GL_NO_ERROR, ("VMSVGA3d: %s -> %#x\n", #a_Expr, iGlError)); \
124 } while (0)
125
126/**
127 * Macro for doing something and then checking for errors during initialization,
128 * doing the same in the other context when enabled.
129 *
130 * This will try both profiles in dual profile builds. Caller must be in the
131 * default context.
132 *
133 * Uses AssertLogRelMsg to indicate trouble.
134 */
135#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
136# define VMSVGA3D_INIT_CHECKED_BOTH(a_pState, a_pContext, a_pOtherCtx, a_Expr) \
137 do \
138 { \
139 for (uint32_t i = 0; i < 64; i++) if (glGetError() == GL_NO_ERROR) break; Assert(glGetError() == GL_NO_ERROR); \
140 a_Expr; \
141 GLenum iGlError = glGetError(); \
142 if (iGlError != GL_NO_ERROR) \
143 { \
144 VMSVGA3D_SET_CURRENT_CONTEXT(a_pState, a_pOtherCtx); \
145 for (uint32_t i = 0; i < 64; i++) if (glGetError() == GL_NO_ERROR) break; Assert(glGetError() == GL_NO_ERROR); \
146 a_Expr; \
147 GLenum iGlError2 = glGetError(); \
148 AssertLogRelMsg(iGlError2 == GL_NO_ERROR, ("VMSVGA3d: %s -> %#x / %#x\n", #a_Expr, iGlError, iGlError2)); \
149 VMSVGA3D_SET_CURRENT_CONTEXT(a_pState, a_pContext); \
150 } \
151 } while (0)
152#else
153# define VMSVGA3D_INIT_CHECKED_BOTH(a_pState, a_pContext, a_pOtherCtx, a_Expr) VMSVGA3D_INIT_CHECKED(a_Expr)
154#endif
155
156
157/*********************************************************************************************************************************
158* Global Variables *
159*********************************************************************************************************************************/
160/* Define the default light parameters as specified by MSDN. */
161/** @todo move out; fetched from Wine */
162const SVGA3dLightData vmsvga3d_default_light =
163{
164 SVGA3D_LIGHTTYPE_DIRECTIONAL, /* type */
165 false, /* inWorldSpace */
166 { 1.0f, 1.0f, 1.0f, 0.0f }, /* diffuse r,g,b,a */
167 { 0.0f, 0.0f, 0.0f, 0.0f }, /* specular r,g,b,a */
168 { 0.0f, 0.0f, 0.0f, 0.0f }, /* ambient r,g,b,a, */
169 { 0.0f, 0.0f, 0.0f }, /* position x,y,z */
170 { 0.0f, 0.0f, 1.0f }, /* direction x,y,z */
171 0.0f, /* range */
172 0.0f, /* falloff */
173 0.0f, 0.0f, 0.0f, /* attenuation 0,1,2 */
174 0.0f, /* theta */
175 0.0f /* phi */
176};
177
178
179/*********************************************************************************************************************************
180* Internal Functions *
181*********************************************************************************************************************************/
182static int vmsvga3dContextDestroyOgl(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid);
183static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid);
184static void vmsvgaColor2GLFloatArray(uint32_t color, GLfloat *pRed, GLfloat *pGreen, GLfloat *pBlue, GLfloat *pAlpha);
185static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData);
186static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]);
187static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type);
188static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext);
189static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, PVMSVGA3DSURFACE pSurface);
190
191/* Generated by VBoxDef2LazyLoad from the VBoxSVGA3D.def and VBoxSVGA3DObjC.def files. */
192extern "C" int ExplicitlyLoadVBoxSVGA3D(bool fResolveAllImports, PRTERRINFO pErrInfo);
193
194
195/**
196 * Checks if the given OpenGL extension is supported.
197 *
198 * @returns true if supported, false if not.
199 * @param pState The VMSVGA3d state.
200 * @param rsMinGLVersion The OpenGL version that introduced this feature
201 * into the core.
202 * @param pszWantedExtension The name of the OpenGL extension we want padded
203 * with one space at each end.
204 * @remarks Init time only.
205 */
206static bool vmsvga3dCheckGLExtension(PVMSVGA3DSTATE pState, float rsMinGLVersion, const char *pszWantedExtension)
207{
208 RT_NOREF(rsMinGLVersion);
209 /* check padding. */
210 Assert(pszWantedExtension[0] == ' ');
211 Assert(pszWantedExtension[1] != ' ');
212 Assert(strchr(&pszWantedExtension[1], ' ') + 1 == strchr(pszWantedExtension, '\0'));
213
214 /* Look it up. */
215 bool fRet = false;
216 if (strstr(pState->pszExtensions, pszWantedExtension))
217 fRet = true;
218
219 /* Temporarily. Later start if (rsMinGLVersion != 0.0 && fActualGLVersion >= rsMinGLVersion) return true; */
220#ifdef RT_OS_DARWIN
221 AssertMsg( rsMinGLVersion == 0.0
222 || fRet == (pState->rsGLVersion >= rsMinGLVersion)
223 || VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE == 2.1,
224 ("%s actual:%d min:%d fRet=%d\n",
225 pszWantedExtension, (int)(pState->rsGLVersion * 10), (int)(rsMinGLVersion * 10), fRet));
226#else
227 AssertMsg(rsMinGLVersion == 0.0 || fRet == (pState->rsGLVersion >= rsMinGLVersion),
228 ("%s actual:%d min:%d fRet=%d\n",
229 pszWantedExtension, (int)(pState->rsGLVersion * 10), (int)(rsMinGLVersion * 10), fRet));
230#endif
231 return fRet;
232}
233
234
235/**
236 * Outputs GL_EXTENSIONS list to the release log.
237 */
238static void vmsvga3dLogRelExtensions(const char *pszPrefix, const char *pszExtensions)
239{
240 /* OpenGL 3.0 interface (glGetString(GL_EXTENSIONS) return NULL). */
241 bool fBuffered = RTLogRelSetBuffering(true);
242
243 /*
244 * Determin the column widths first.
245 */
246 size_t acchWidths[4] = { 1, 1, 1, 1 };
247 uint32_t i;
248 const char *psz = pszExtensions;
249 for (i = 0; ; i++)
250 {
251 while (*psz == ' ')
252 psz++;
253 if (!*psz)
254 break;
255
256 const char *pszEnd = strchr(psz, ' ');
257 AssertBreak(pszEnd);
258 size_t cch = pszEnd - psz;
259
260 uint32_t iColumn = i % RT_ELEMENTS(acchWidths);
261 if (acchWidths[iColumn] < cch)
262 acchWidths[iColumn] = cch;
263
264 psz = pszEnd;
265 }
266
267 /*
268 * Output it.
269 */
270 LogRel(("VMSVGA3d: %sOpenGL extensions (%d):", pszPrefix, i));
271 psz = pszExtensions;
272 for (i = 0; ; i++)
273 {
274 while (*psz == ' ')
275 psz++;
276 if (!*psz)
277 break;
278
279 const char *pszEnd = strchr(psz, ' ');
280 AssertBreak(pszEnd);
281 size_t cch = pszEnd - psz;
282
283 uint32_t iColumn = i % RT_ELEMENTS(acchWidths);
284 if (iColumn == 0)
285 LogRel(("\nVMSVGA3d: %-*.*s", acchWidths[iColumn], cch, psz));
286 else if (iColumn != RT_ELEMENTS(acchWidths) - 1)
287 LogRel((" %-*.*s", acchWidths[iColumn], cch, psz));
288 else
289 LogRel((" %.*s", cch, psz));
290
291 psz = pszEnd;
292 }
293
294 RTLogRelSetBuffering(fBuffered);
295 LogRel(("\n"));
296}
297
298/**
299 * Gathers the GL_EXTENSIONS list, storing it as a space padded list at
300 * @a ppszExtensions.
301 *
302 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY
303 * @param ppszExtensions Pointer to the string pointer. Free with RTStrFree.
304 * @param fGLProfileVersion The OpenGL profile version.
305 */
306static int vmsvga3dGatherExtensions(char **ppszExtensions, float fGLProfileVersion)
307{
308 int rc;
309 *ppszExtensions = NULL;
310
311 /*
312 * Try the old glGetString interface first.
313 */
314 const char *pszExtensions = (const char *)glGetString(GL_EXTENSIONS);
315 if (pszExtensions)
316 {
317 rc = RTStrAAppendExN(ppszExtensions, 3, " ", (size_t)1, pszExtensions, RTSTR_MAX, " ", (size_t)1);
318 AssertLogRelRCReturn(rc, rc);
319 }
320 else
321 {
322 /*
323 * The new interface where each extension string is retrieved separately.
324 * Note! Cannot use VMSVGA3D_INIT_CHECKED_GL_GET_INTEGER_VALUE here because
325 * the above GL_EXTENSIONS error lingers on darwin. sucks.
326 */
327#ifndef GL_NUM_EXTENSIONS
328# define GL_NUM_EXTENSIONS 0x821D
329#endif
330 GLint cExtensions = 1024;
331 glGetIntegerv(GL_NUM_EXTENSIONS, &cExtensions);
332 Assert(cExtensions != 1024);
333
334 PFNGLGETSTRINGIPROC pfnGlGetStringi = (PFNGLGETSTRINGIPROC)OGLGETPROCADDRESS("glGetStringi");
335 AssertLogRelReturn(pfnGlGetStringi, VERR_NOT_SUPPORTED);
336
337 rc = RTStrAAppend(ppszExtensions, " ");
338 for (GLint i = 0; RT_SUCCESS(rc) && i < cExtensions; i++)
339 {
340 const char *pszExt = (const char *)pfnGlGetStringi(GL_EXTENSIONS, i);
341 if (pszExt)
342 rc = RTStrAAppendExN(ppszExtensions, 2, pfnGlGetStringi(GL_EXTENSIONS, i), RTSTR_MAX, " ", (size_t)1);
343 }
344 AssertRCReturn(rc, rc);
345 }
346
347#if 1
348 /*
349 * Add extensions promoted into the core OpenGL profile.
350 */
351 static const struct
352 {
353 float fGLVersion;
354 const char *pszzExtensions;
355 } s_aPromotedExtensions[] =
356 {
357 {
358 1.1f,
359 " GL_EXT_vertex_array \0"
360 " GL_EXT_polygon_offset \0"
361 " GL_EXT_blend_logic_op \0"
362 " GL_EXT_texture \0"
363 " GL_EXT_copy_texture \0"
364 " GL_EXT_subtexture \0"
365 " GL_EXT_texture_object \0"
366 " GL_ARB_framebuffer_object \0"
367 " GL_ARB_map_buffer_range \0"
368 " GL_ARB_vertex_array_object \0"
369 "\0"
370 },
371 {
372 1.2f,
373 " EXT_texture3D \0"
374 " EXT_bgra \0"
375 " EXT_packed_pixels \0"
376 " EXT_rescale_normal \0"
377 " EXT_separate_specular_color \0"
378 " SGIS_texture_edge_clamp \0"
379 " SGIS_texture_lod \0"
380 " EXT_draw_range_elements \0"
381 "\0"
382 },
383 {
384 1.3f,
385 " GL_ARB_texture_compression \0"
386 " GL_ARB_texture_cube_map \0"
387 " GL_ARB_multisample \0"
388 " GL_ARB_multitexture \0"
389 " GL_ARB_texture_env_add \0"
390 " GL_ARB_texture_env_combine \0"
391 " GL_ARB_texture_env_dot3 \0"
392 " GL_ARB_texture_border_clamp \0"
393 " GL_ARB_transpose_matrix \0"
394 "\0"
395 },
396 {
397 1.5f,
398 " GL_SGIS_generate_mipmap \0"
399 /*" GL_NV_blend_equare \0"*/
400 " GL_ARB_depth_texture \0"
401 " GL_ARB_shadow \0"
402 " GL_EXT_fog_coord \0"
403 " GL_EXT_multi_draw_arrays \0"
404 " GL_ARB_point_parameters \0"
405 " GL_EXT_secondary_color \0"
406 " GL_EXT_blend_func_separate \0"
407 " GL_EXT_stencil_wrap \0"
408 " GL_ARB_texture_env_crossbar \0"
409 " GL_EXT_texture_lod_bias \0"
410 " GL_ARB_texture_mirrored_repeat \0"
411 " GL_ARB_window_pos \0"
412 "\0"
413 },
414 {
415 1.6f,
416 " GL_ARB_vertex_buffer_object \0"
417 " GL_ARB_occlusion_query \0"
418 " GL_EXT_shadow_funcs \0"
419 },
420 {
421 2.0f,
422 " GL_ARB_shader_objects \0" /*??*/
423 " GL_ARB_vertex_shader \0" /*??*/
424 " GL_ARB_fragment_shader \0" /*??*/
425 " GL_ARB_shading_language_100 \0" /*??*/
426 " GL_ARB_draw_buffers \0"
427 " GL_ARB_texture_non_power_of_two \0"
428 " GL_ARB_point_sprite \0"
429 " GL_ATI_separate_stencil \0"
430 " GL_EXT_stencil_two_side \0"
431 "\0"
432 },
433 {
434 2.1f,
435 " GL_ARB_pixel_buffer_object \0"
436 " GL_EXT_texture_sRGB \0"
437 "\0"
438 },
439 {
440 3.0f,
441 " GL_ARB_framebuffer_object \0"
442 " GL_ARB_map_buffer_range \0"
443 " GL_ARB_vertex_array_object \0"
444 "\0"
445 },
446 {
447 3.1f,
448 " GL_ARB_copy_buffer \0"
449 " GL_ARB_uniform_buffer_object \0"
450 "\0"
451 },
452 {
453 3.2f,
454 " GL_ARB_vertex_array_bgra \0"
455 " GL_ARB_draw_elements_base_vertex \0"
456 " GL_ARB_fragment_coord_conventions \0"
457 " GL_ARB_provoking_vertex \0"
458 " GL_ARB_seamless_cube_map \0"
459 " GL_ARB_texture_multisample \0"
460 " GL_ARB_depth_clamp \0"
461 " GL_ARB_sync \0"
462 " GL_ARB_geometry_shader4 \0" /*??*/
463 "\0"
464 },
465 {
466 3.3f,
467 " GL_ARB_blend_func_extended \0"
468 " GL_ARB_sampler_objects \0"
469 " GL_ARB_explicit_attrib_location \0"
470 " GL_ARB_occlusion_query2 \0"
471 " GL_ARB_shader_bit_encoding \0"
472 " GL_ARB_texture_rgb10_a2ui \0"
473 " GL_ARB_texture_swizzle \0"
474 " GL_ARB_timer_query \0"
475 " GL_ARB_vertex_type_2_10_10_10_rev \0"
476 "\0"
477 },
478 {
479 4.0f,
480 " GL_ARB_texture_query_lod \0"
481 " GL_ARB_draw_indirect \0"
482 " GL_ARB_gpu_shader5 \0"
483 " GL_ARB_gpu_shader_fp64 \0"
484 " GL_ARB_shader_subroutine \0"
485 " GL_ARB_tessellation_shader \0"
486 " GL_ARB_texture_buffer_object_rgb32 \0"
487 " GL_ARB_texture_cube_map_array \0"
488 " GL_ARB_texture_gather \0"
489 " GL_ARB_transform_feedback2 \0"
490 " GL_ARB_transform_feedback3 \0"
491 "\0"
492 },
493 {
494 4.1f,
495 " GL_ARB_ES2_compatibility \0"
496 " GL_ARB_get_program_binary \0"
497 " GL_ARB_separate_shader_objects \0"
498 " GL_ARB_shader_precision \0"
499 " GL_ARB_vertex_attrib_64bit \0"
500 " GL_ARB_viewport_array \0"
501 "\0"
502 }
503 };
504
505 uint32_t cPromoted = 0;
506 for (uint32_t i = 0; i < RT_ELEMENTS(s_aPromotedExtensions) && s_aPromotedExtensions[i].fGLVersion <= fGLProfileVersion; i++)
507 {
508 const char *pszExt = s_aPromotedExtensions[i].pszzExtensions;
509 while (*pszExt)
510 {
511# ifdef VBOX_STRICT
512 size_t cchExt = strlen(pszExt);
513 Assert(cchExt > 3);
514 Assert(pszExt[0] == ' ');
515 Assert(pszExt[1] != ' ');
516 Assert(pszExt[cchExt - 2] != ' ');
517 Assert(pszExt[cchExt - 1] == ' ');
518# endif
519
520 if (strstr(*ppszExtensions, pszExt) == NULL)
521 {
522 if (cPromoted++ == 0)
523 {
524 rc = RTStrAAppend(ppszExtensions, " <promoted-extensions:> <promoted-extensions:> <promoted-extensions:> ");
525 AssertRCReturn(rc, rc);
526 }
527
528 rc = RTStrAAppend(ppszExtensions, pszExt);
529 AssertRCReturn(rc, rc);
530 }
531
532 pszExt = strchr(pszExt, '\0') + 1;
533 }
534 }
535#endif
536
537 return VINF_SUCCESS;
538}
539
540/** Check whether this is an Intel GL driver.
541 *
542 * @returns true if this seems to be some Intel graphics.
543 */
544static bool vmsvga3dIsVendorIntel(void)
545{
546 return RTStrNICmp((char *)glGetString(GL_VENDOR), "Intel", 5) == 0;
547}
548
549/**
550 * @interface_method_impl{VBOXVMSVGASHADERIF,pfnSwitchInitProfile}
551 */
552static DECLCALLBACK(void) vmsvga3dShaderIfSwitchInitProfile(PVBOXVMSVGASHADERIF pThis, bool fOtherProfile)
553{
554#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
555 PVMSVGA3DSTATE pState = RT_FROM_MEMBER(pThis, VMSVGA3DSTATE, ShaderIf);
556 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pState->papContexts[fOtherProfile ? 2 : 1]);
557#else
558 NOREF(pThis);
559 NOREF(fOtherProfile);
560#endif
561}
562
563
564/**
565 * @interface_method_impl{VBOXVMSVGASHADERIF,pfnGetNextExtension}
566 */
567static DECLCALLBACK(bool) vmsvga3dShaderIfGetNextExtension(PVBOXVMSVGASHADERIF pThis, void **ppvEnumCtx,
568 char *pszBuf, size_t cbBuf, bool fOtherProfile)
569{
570 PVMSVGA3DSTATE pState = RT_FROM_MEMBER(pThis, VMSVGA3DSTATE, ShaderIf);
571 const char *pszCur = *ppvEnumCtx ? (const char *)*ppvEnumCtx
572 : fOtherProfile ? pState->pszOtherExtensions : pState->pszExtensions;
573 while (*pszCur == ' ')
574 pszCur++;
575 if (!*pszCur)
576 return false;
577
578 const char *pszEnd = strchr(pszCur, ' ');
579 AssertReturn(pszEnd, false);
580 size_t cch = pszEnd - pszCur;
581 if (cch < cbBuf)
582 {
583 memcpy(pszBuf, pszCur, cch);
584 pszBuf[cch] = '\0';
585 }
586 else if (cbBuf > 0)
587 {
588 memcpy(pszBuf, "<overflow>", RT_MIN(sizeof("<overflow>"), cbBuf));
589 pszBuf[cbBuf - 1] = '\0';
590 }
591
592 *ppvEnumCtx = (void *)pszEnd;
593 return true;
594}
595
596
597/**
598 * Initializes the VMSVGA3D state during VGA device construction.
599 *
600 * Failure are generally not fatal, 3D support will just be disabled.
601 *
602 * @returns VBox status code.
603 * @param pDevIns The device instance.
604 * @param pThis The shared VGA/VMSVGA state where svga.p3dState will be
605 * modified.
606 * @param pThisCC The VGA/VMSVGA state for ring-3.
607 */
608static DECLCALLBACK(int) vmsvga3dBackInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
609{
610 int rc;
611 RT_NOREF(pDevIns, pThis, pThisCC);
612
613 AssertCompile(GL_TRUE == 1);
614 AssertCompile(GL_FALSE == 0);
615
616#ifdef VMSVGA3D_DYNAMIC_LOAD
617 rc = glLdrInit(pDevIns);
618 if (RT_FAILURE(rc))
619 {
620 LogRel(("VMSVGA3d: Error loading OpenGL library and resolving necessary functions: %Rrc\n", rc));
621 return rc;
622 }
623#endif
624
625 /*
626 * Load and resolve imports from the external shared libraries.
627 */
628 RTERRINFOSTATIC ErrInfo;
629 rc = ExplicitlyLoadVBoxSVGA3D(true /*fResolveAllImports*/, RTErrInfoInitStatic(&ErrInfo));
630 if (RT_FAILURE(rc))
631 {
632 LogRel(("VMSVGA3d: Error loading VBoxSVGA3D and resolving necessary functions: %Rrc - %s\n", rc, ErrInfo.Core.pszMsg));
633 return rc;
634 }
635#ifdef RT_OS_DARWIN
636 rc = ExplicitlyLoadVBoxSVGA3DObjC(true /*fResolveAllImports*/, RTErrInfoInitStatic(&ErrInfo));
637 if (RT_FAILURE(rc))
638 {
639 LogRel(("VMSVGA3d: Error loading VBoxSVGA3DObjC and resolving necessary functions: %Rrc - %s\n", rc, ErrInfo.Core.pszMsg));
640 return rc;
641 }
642#endif
643
644#ifdef RT_OS_WINDOWS
645 /* Create event semaphore and async IO thread. */
646 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
647 rc = RTSemEventCreate(&pState->WndRequestSem);
648 if (RT_SUCCESS(rc))
649 {
650 rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dWindowThread, pState->WndRequestSem, 0, RTTHREADTYPE_GUI, 0,
651 "VMSVGA3DWND");
652 if (RT_SUCCESS(rc))
653 return VINF_SUCCESS;
654
655 /* bail out. */
656 LogRel(("VMSVGA3d: RTThreadCreate failed: %Rrc\n", rc));
657 RTSemEventDestroy(pState->WndRequestSem);
658 }
659 else
660 LogRel(("VMSVGA3d: RTSemEventCreate failed: %Rrc\n", rc));
661 return rc;
662#else
663 return VINF_SUCCESS;
664#endif
665}
666
667static int vmsvga3dLoadGLFunctions(PVMSVGA3DSTATE pState)
668{
669 /* A strict approach to get a proc address as recommended by Khronos:
670 * - "If the function is a core OpenGL function, then we need to check the OpenGL version".
671 * - "If the function is an extension, we need to check to see if the extension is supported."
672 */
673
674/* Get a function address, return VERR_NOT_IMPLEMENTED on failure. */
675#define GLGETPROC_(ProcType, ProcName, NameSuffix) do { \
676 pState->ext.ProcName = (ProcType)OGLGETPROCADDRESS(#ProcName NameSuffix); \
677 AssertLogRelMsgReturn(pState->ext.ProcName, (#ProcName NameSuffix " missing"), VERR_NOT_IMPLEMENTED); \
678} while(0)
679
680/* Get an optional function address. LogRel on failure. */
681#define GLGETPROCOPT_(ProcType, ProcName, NameSuffix) do { \
682 pState->ext.ProcName = (ProcType)OGLGETPROCADDRESS(#ProcName NameSuffix); \
683 if (!pState->ext.ProcName) \
684 { \
685 LogRel(("VMSVGA3d: missing optional %s\n", #ProcName NameSuffix)); \
686 AssertFailed(); \
687 } \
688} while(0)
689
690 /* OpenGL 2.0 or earlier core. Do not bother with extensions. */
691 GLGETPROC_(PFNGLGENQUERIESPROC , glGenQueries, "");
692 GLGETPROC_(PFNGLDELETEQUERIESPROC , glDeleteQueries, "");
693 GLGETPROC_(PFNGLBEGINQUERYPROC , glBeginQuery, "");
694 GLGETPROC_(PFNGLENDQUERYPROC , glEndQuery, "");
695 GLGETPROC_(PFNGLGETQUERYOBJECTUIVPROC , glGetQueryObjectuiv, "");
696 GLGETPROC_(PFNGLTEXIMAGE3DPROC , glTexImage3D, "");
697 GLGETPROC_(PFNGLTEXSUBIMAGE3DPROC , glTexSubImage3D, "");
698 GLGETPROC_(PFNGLGETCOMPRESSEDTEXIMAGEPROC , glGetCompressedTexImage, "");
699 GLGETPROC_(PFNGLCOMPRESSEDTEXIMAGE2DPROC , glCompressedTexImage2D, "");
700 GLGETPROC_(PFNGLCOMPRESSEDTEXIMAGE3DPROC , glCompressedTexImage3D, "");
701 GLGETPROC_(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC , glCompressedTexSubImage2D, "");
702 GLGETPROC_(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC , glCompressedTexSubImage3D, "");
703 GLGETPROC_(PFNGLPOINTPARAMETERFPROC , glPointParameterf, "");
704 GLGETPROC_(PFNGLBLENDEQUATIONSEPARATEPROC , glBlendEquationSeparate, "");
705 GLGETPROC_(PFNGLBLENDFUNCSEPARATEPROC , glBlendFuncSeparate, "");
706 GLGETPROC_(PFNGLSTENCILOPSEPARATEPROC , glStencilOpSeparate, "");
707 GLGETPROC_(PFNGLSTENCILFUNCSEPARATEPROC , glStencilFuncSeparate, "");
708 GLGETPROC_(PFNGLBINDBUFFERPROC , glBindBuffer, "");
709 GLGETPROC_(PFNGLDELETEBUFFERSPROC , glDeleteBuffers, "");
710 GLGETPROC_(PFNGLGENBUFFERSPROC , glGenBuffers, "");
711 GLGETPROC_(PFNGLBUFFERDATAPROC , glBufferData, "");
712 GLGETPROC_(PFNGLMAPBUFFERPROC , glMapBuffer, "");
713 GLGETPROC_(PFNGLUNMAPBUFFERPROC , glUnmapBuffer, "");
714 GLGETPROC_(PFNGLENABLEVERTEXATTRIBARRAYPROC , glEnableVertexAttribArray, "");
715 GLGETPROC_(PFNGLDISABLEVERTEXATTRIBARRAYPROC , glDisableVertexAttribArray, "");
716 GLGETPROC_(PFNGLVERTEXATTRIBPOINTERPROC , glVertexAttribPointer, "");
717 GLGETPROC_(PFNGLACTIVETEXTUREPROC , glActiveTexture, "");
718 /* glGetProgramivARB determines implementation limits for the program
719 * target (GL_FRAGMENT_PROGRAM_ARB, GL_VERTEX_PROGRAM_ARB).
720 * It differs from glGetProgramiv, which returns a parameter from a program object.
721 */
722 GLGETPROC_(PFNGLGETPROGRAMIVARBPROC , glGetProgramivARB, "");
723 GLGETPROC_(PFNGLFOGCOORDPOINTERPROC , glFogCoordPointer, "");
724#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x102
725 GLGETPROC_(PFNGLBLENDCOLORPROC , glBlendColor, "");
726 GLGETPROC_(PFNGLBLENDEQUATIONPROC , glBlendEquation, "");
727#endif
728#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x103
729 GLGETPROC_(PFNGLCLIENTACTIVETEXTUREPROC , glClientActiveTexture, "");
730#endif
731 GLGETPROC_(PFNGLDRAWBUFFERSPROC , glDrawBuffers, "");
732 GLGETPROC_(PFNGLCREATESHADERPROC , glCreateShader, "");
733 GLGETPROC_(PFNGLSHADERSOURCEPROC , glShaderSource, "");
734 GLGETPROC_(PFNGLCOMPILESHADERPROC , glCompileShader, "");
735 GLGETPROC_(PFNGLGETSHADERIVPROC , glGetShaderiv, "");
736 GLGETPROC_(PFNGLGETSHADERINFOLOGPROC , glGetShaderInfoLog, "");
737 GLGETPROC_(PFNGLCREATEPROGRAMPROC , glCreateProgram, "");
738 GLGETPROC_(PFNGLATTACHSHADERPROC , glAttachShader, "");
739 GLGETPROC_(PFNGLLINKPROGRAMPROC , glLinkProgram, "");
740 GLGETPROC_(PFNGLGETPROGRAMIVPROC , glGetProgramiv, "");
741 GLGETPROC_(PFNGLGETPROGRAMINFOLOGPROC , glGetProgramInfoLog, "");
742 GLGETPROC_(PFNGLUSEPROGRAMPROC , glUseProgram, "");
743 GLGETPROC_(PFNGLGETUNIFORMLOCATIONPROC , glGetUniformLocation, "");
744 GLGETPROC_(PFNGLUNIFORM1IPROC , glUniform1i, "");
745 GLGETPROC_(PFNGLUNIFORM4FVPROC , glUniform4fv, "");
746 GLGETPROC_(PFNGLDETACHSHADERPROC , glDetachShader, "");
747 GLGETPROC_(PFNGLDELETESHADERPROC , glDeleteShader, "");
748 GLGETPROC_(PFNGLDELETEPROGRAMPROC , glDeleteProgram, "");
749
750 GLGETPROC_(PFNGLVERTEXATTRIB4FVPROC , glVertexAttrib4fv, "");
751 GLGETPROC_(PFNGLVERTEXATTRIB4UBVPROC , glVertexAttrib4ubv, "");
752 GLGETPROC_(PFNGLVERTEXATTRIB4NUBVPROC , glVertexAttrib4Nubv, "");
753 GLGETPROC_(PFNGLVERTEXATTRIB4SVPROC , glVertexAttrib4sv, "");
754 GLGETPROC_(PFNGLVERTEXATTRIB4NSVPROC , glVertexAttrib4Nsv, "");
755 GLGETPROC_(PFNGLVERTEXATTRIB4NUSVPROC , glVertexAttrib4Nusv, "");
756
757 /* OpenGL 3.0 core, GL_ARB_instanced_arrays. Same functions names in the ARB and core specs. */
758 if ( pState->rsGLVersion >= 3.0f
759 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_framebuffer_object "))
760 {
761 GLGETPROC_(PFNGLISRENDERBUFFERPROC , glIsRenderbuffer, "");
762 GLGETPROC_(PFNGLBINDRENDERBUFFERPROC , glBindRenderbuffer, "");
763 GLGETPROC_(PFNGLDELETERENDERBUFFERSPROC , glDeleteRenderbuffers, "");
764 GLGETPROC_(PFNGLGENRENDERBUFFERSPROC , glGenRenderbuffers, "");
765 GLGETPROC_(PFNGLRENDERBUFFERSTORAGEPROC , glRenderbufferStorage, "");
766 GLGETPROC_(PFNGLGETRENDERBUFFERPARAMETERIVPROC , glGetRenderbufferParameteriv, "");
767 GLGETPROC_(PFNGLISFRAMEBUFFERPROC , glIsFramebuffer, "");
768 GLGETPROC_(PFNGLBINDFRAMEBUFFERPROC , glBindFramebuffer, "");
769 GLGETPROC_(PFNGLDELETEFRAMEBUFFERSPROC , glDeleteFramebuffers, "");
770 GLGETPROC_(PFNGLGENFRAMEBUFFERSPROC , glGenFramebuffers, "");
771 GLGETPROC_(PFNGLCHECKFRAMEBUFFERSTATUSPROC , glCheckFramebufferStatus, "");
772 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE1DPROC , glFramebufferTexture1D, "");
773 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE2DPROC , glFramebufferTexture2D, "");
774 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE3DPROC , glFramebufferTexture3D, "");
775 GLGETPROC_(PFNGLFRAMEBUFFERRENDERBUFFERPROC , glFramebufferRenderbuffer, "");
776 GLGETPROC_(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC , glGetFramebufferAttachmentParameteriv, "");
777 GLGETPROC_(PFNGLGENERATEMIPMAPPROC , glGenerateMipmap, "");
778 GLGETPROC_(PFNGLBLITFRAMEBUFFERPROC , glBlitFramebuffer, "");
779 GLGETPROC_(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC , glRenderbufferStorageMultisample, "");
780 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURELAYERPROC , glFramebufferTextureLayer, "");
781 }
782
783 /* OpenGL 3.1 core, GL_ARB_draw_instanced, GL_EXT_draw_instanced. */
784 if (pState->rsGLVersion >= 3.1f)
785 {
786 GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "");
787 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "");
788 }
789 else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_draw_instanced "))
790 {
791 GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "ARB");
792 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "ARB");
793 }
794 else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_draw_instanced "))
795 {
796 GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "EXT");
797 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "EXT");
798 }
799
800 /* OpenGL 3.2 core, GL_ARB_draw_elements_base_vertex. Same functions names in the ARB and core specs. */
801 if ( pState->rsGLVersion >= 3.2f
802 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_draw_elements_base_vertex "))
803 {
804 GLGETPROC_(PFNGLDRAWELEMENTSBASEVERTEXPROC , glDrawElementsBaseVertex, "");
805 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC , glDrawElementsInstancedBaseVertex, "");
806 }
807
808 /* Optional. OpenGL 3.2 core, GL_ARB_provoking_vertex. Same functions names in the ARB and core specs. */
809 if ( pState->rsGLVersion >= 3.2f
810 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_provoking_vertex "))
811 {
812 GLGETPROCOPT_(PFNGLPROVOKINGVERTEXPROC , glProvokingVertex, "");
813 }
814
815 /* OpenGL 3.3 core, GL_ARB_instanced_arrays. */
816 if (pState->rsGLVersion >= 3.3f)
817 {
818 GLGETPROC_(PFNGLVERTEXATTRIBDIVISORPROC , glVertexAttribDivisor, "");
819 }
820 else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_instanced_arrays "))
821 {
822 GLGETPROC_(PFNGLVERTEXATTRIBDIVISORARBPROC , glVertexAttribDivisor, "ARB");
823 }
824
825#undef GLGETPROCOPT_
826#undef GLGETPROC_
827
828 return VINF_SUCCESS;
829}
830
831
832DECLINLINE(GLenum) vmsvga3dCubemapFaceFromIndex(uint32_t iFace)
833{
834 GLint Face;
835 switch (iFace)
836 {
837 case 0: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; break;
838 case 1: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; break;
839 case 2: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; break;
840 case 3: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; break;
841 case 4: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; break;
842 default:
843 case 5: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; break;
844 }
845 return Face;
846}
847
848
849/* We must delay window creation until the PowerOn phase. Init is too early and will cause failures. */
850static DECLCALLBACK(int) vmsvga3dBackPowerOn(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
851{
852 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
853 AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY);
854 PVMSVGA3DCONTEXT pContext;
855#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
856 PVMSVGA3DCONTEXT pOtherCtx;
857#endif
858 int rc;
859 RT_NOREF(pDevIns, pThis);
860
861 if (pState->rsGLVersion != 0.0)
862 return VINF_SUCCESS; /* already initialized (load state) */
863
864 /*
865 * OpenGL function calls aren't possible without a valid current context, so create a fake one here.
866 */
867 rc = vmsvga3dContextDefineOgl(pThisCC, 1, VMSVGA3D_DEF_CTX_F_INIT);
868 AssertRCReturn(rc, rc);
869
870 pContext = pState->papContexts[1];
871 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
872
873#ifdef VMSVGA3D_DYNAMIC_LOAD
874 /* Context is set and it is possible now to resolve extension functions. */
875 rc = glLdrGetExtFunctions(pDevIns);
876 if (RT_FAILURE(rc))
877 {
878 LogRel(("VMSVGA3d: Error resolving extension functions: %Rrc\n", rc));
879 return rc;
880 }
881#endif
882
883 LogRel(("VMSVGA3d: OpenGL version: %s\n"
884 "VMSVGA3d: OpenGL Vendor: %s\n"
885 "VMSVGA3d: OpenGL Renderer: %s\n"
886 "VMSVGA3d: OpenGL shader language version: %s\n",
887 glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER),
888 glGetString(GL_SHADING_LANGUAGE_VERSION)));
889
890 rc = vmsvga3dGatherExtensions(&pState->pszExtensions, VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE);
891 AssertRCReturn(rc, rc);
892 vmsvga3dLogRelExtensions("", pState->pszExtensions);
893
894 pState->rsGLVersion = atof((const char *)glGetString(GL_VERSION));
895
896
897#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
898 /*
899 * Get the extension list for the alternative profile so we can better
900 * figure out the shader model and stuff.
901 */
902 rc = vmsvga3dContextDefineOgl(pThisCC, 2, VMSVGA3D_DEF_CTX_F_INIT | VMSVGA3D_DEF_CTX_F_OTHER_PROFILE);
903 AssertLogRelRCReturn(rc, rc);
904 pContext = pState->papContexts[1]; /* Array may have been reallocated. */
905
906 pOtherCtx = pState->papContexts[2];
907 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx);
908
909 LogRel(("VMSVGA3d: Alternative OpenGL version: %s\n"
910 "VMSVGA3d: Alternative OpenGL Vendor: %s\n"
911 "VMSVGA3d: Alternative OpenGL Renderer: %s\n"
912 "VMSVGA3d: Alternative OpenGL shader language version: %s\n",
913 glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER),
914 glGetString(GL_SHADING_LANGUAGE_VERSION)));
915
916 rc = vmsvga3dGatherExtensions(&pState->pszOtherExtensions, VBOX_VMSVGA3D_OTHER_OGL_PROFILE);
917 AssertRCReturn(rc, rc);
918 vmsvga3dLogRelExtensions("Alternative ", pState->pszOtherExtensions);
919
920 pState->rsOtherGLVersion = atof((const char *)glGetString(GL_VERSION));
921
922 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
923#else
924 pState->pszOtherExtensions = (char *)"";
925 pState->rsOtherGLVersion = pState->rsGLVersion;
926#endif
927
928 /*
929 * Resolve GL function pointers and store them in pState->ext.
930 */
931 rc = vmsvga3dLoadGLFunctions(pState);
932 if (RT_FAILURE(rc))
933 {
934 LogRel(("VMSVGA3d: missing required OpenGL function or extension; aborting\n"));
935 return rc;
936 }
937
938 /*
939 * Initialize the capabilities with sensible defaults.
940 */
941 pState->caps.maxActiveLights = 1;
942 pState->caps.maxTextures = 1;
943 pState->caps.maxClipDistances = 4;
944 pState->caps.maxColorAttachments = 1;
945 pState->caps.maxRectangleTextureSize = 2048;
946 pState->caps.maxTextureAnisotropy = 1;
947 pState->caps.maxVertexShaderInstructions = 1024;
948 pState->caps.maxFragmentShaderInstructions = 1024;
949 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_NONE;
950 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_NONE;
951 pState->caps.flPointSize[0] = 1;
952 pState->caps.flPointSize[1] = 1;
953
954 /*
955 * Query capabilities
956 */
957 pState->caps.fS3TCSupported = vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_texture_compression_s3tc ");
958 pState->caps.fTextureFilterAnisotropicSupported = vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_texture_filter_anisotropic ");
959
960 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetIntegerv(GL_MAX_LIGHTS, &pState->caps.maxActiveLights));
961 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &pState->caps.maxTextures));
962#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE /* The alternative profile has a higher number here (ati/darwin). */
963 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx);
964 VMSVGA3D_INIT_CHECKED_BOTH(pState, pOtherCtx, pContext, glGetIntegerv(GL_MAX_CLIP_DISTANCES, &pState->caps.maxClipDistances));
965 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
966#else
967 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_CLIP_DISTANCES, &pState->caps.maxClipDistances));
968#endif
969 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &pState->caps.maxColorAttachments));
970 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, &pState->caps.maxRectangleTextureSize));
971 if (pState->caps.fTextureFilterAnisotropicSupported)
972 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &pState->caps.maxTextureAnisotropy));
973 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pState->caps.flPointSize));
974
975 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
976 pState->ext.glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
977 &pState->caps.maxFragmentShaderTemps));
978 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
979 pState->ext.glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
980 &pState->caps.maxFragmentShaderInstructions));
981 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
982 pState->ext.glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
983 &pState->caps.maxVertexShaderTemps));
984 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
985 pState->ext.glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
986 &pState->caps.maxVertexShaderInstructions));
987
988 /* http://http://www.opengl.org/wiki/Detecting_the_Shader_Model
989 * ARB Assembly Language
990 * These are done through testing the presence of extensions. You should test them in this order:
991 * GL_NV_gpu_program4: SM 4.0 or better.
992 * GL_NV_vertex_program3: SM 3.0 or better.
993 * GL_ARB_fragment_program: SM 2.0 or better.
994 * ATI does not support higher than SM 2.0 functionality in assembly shaders.
995 *
996 */
997 /** @todo distinguish between vertex and pixel shaders??? */
998#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE /* The alternative profile has a higher number here (ati/darwin). */
999 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx);
1000 const char *pszShadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1001 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
1002#else
1003 const char *pszShadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1004#endif
1005 float v = pszShadingLanguageVersion ? atof(pszShadingLanguageVersion) : 0.0f;
1006 if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_NV_gpu_program4 ")
1007 || strstr(pState->pszOtherExtensions, " GL_NV_gpu_program4 "))
1008 {
1009 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_40;
1010 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_40;
1011 }
1012 else
1013 if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_NV_vertex_program3 ")
1014 || strstr(pState->pszOtherExtensions, " GL_NV_vertex_program3 ")
1015 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_shader_texture_lod ") /* Wine claims this suggests SM 3.0 support */
1016 || strstr(pState->pszOtherExtensions, " GL_ARB_shader_texture_lod ")
1017 )
1018 {
1019 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_30;
1020 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_30;
1021 }
1022 else
1023 if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_fragment_program ")
1024 || strstr(pState->pszOtherExtensions, " GL_ARB_fragment_program "))
1025 {
1026 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_20;
1027 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_20;
1028 }
1029 else
1030 {
1031 LogRel(("VMSVGA3D: WARNING: unknown support for assembly shaders!!\n"));
1032 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_11;
1033 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_11;
1034 }
1035
1036 /* Now check the shading language version, in case it indicates a higher supported version. */
1037 if (v >= 3.30f)
1038 {
1039 pState->caps.vertexShaderVersion = RT_MAX(pState->caps.vertexShaderVersion, SVGA3DVSVERSION_40);
1040 pState->caps.fragmentShaderVersion = RT_MAX(pState->caps.fragmentShaderVersion, SVGA3DPSVERSION_40);
1041 }
1042 else
1043 if (v >= 1.20f)
1044 {
1045 pState->caps.vertexShaderVersion = RT_MAX(pState->caps.vertexShaderVersion, SVGA3DVSVERSION_20);
1046 pState->caps.fragmentShaderVersion = RT_MAX(pState->caps.fragmentShaderVersion, SVGA3DPSVERSION_20);
1047 }
1048
1049 if ( !vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_vertex_array_bgra ")
1050 && !vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_vertex_array_bgra "))
1051 {
1052 LogRel(("VMSVGA3D: WARNING: Missing required extension GL_ARB_vertex_array_bgra (d3dcolor)!!!\n"));
1053 }
1054
1055 /*
1056 * Tweak capabilities.
1057 */
1058 /* Intel Windows drivers return 31, while the guest expects 32 at least. */
1059 if ( pState->caps.maxVertexShaderTemps < 32
1060 && vmsvga3dIsVendorIntel())
1061 pState->caps.maxVertexShaderTemps = 32;
1062
1063#if 0
1064 SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = 11,
1065 SVGA3D_DEVCAP_QUERY_TYPES = 15,
1066 SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = 16,
1067 SVGA3D_DEVCAP_MAX_POINT_SIZE = 17,
1068 SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = 18,
1069 SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = 21,
1070 SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = 22,
1071 SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = 23,
1072 SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = 24,
1073 SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = 25,
1074 SVGA3D_DEVCAP_MAX_VERTEX_INDEX = 26,
1075 SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = 28,
1076 SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = 29,
1077 SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = 30,
1078 SVGA3D_DEVCAP_TEXTURE_OPS = 31,
1079 SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = 32,
1080 SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = 33,
1081 SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = 34,
1082 SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = 35,
1083 SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = 36,
1084 SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = 37,
1085 SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = 38,
1086 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = 39,
1087 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = 40,
1088 SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = 41,
1089 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = 42,
1090 SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = 43,
1091 SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = 44,
1092 SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = 45,
1093 SVGA3D_DEVCAP_SURFACEFMT_DXT1 = 46,
1094 SVGA3D_DEVCAP_SURFACEFMT_DXT2 = 47,
1095 SVGA3D_DEVCAP_SURFACEFMT_DXT3 = 48,
1096 SVGA3D_DEVCAP_SURFACEFMT_DXT4 = 49,
1097 SVGA3D_DEVCAP_SURFACEFMT_DXT5 = 50,
1098 SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = 51,
1099 SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = 52,
1100 SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = 53,
1101 SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = 54,
1102 SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = 55,
1103 SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = 56,
1104 SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = 57,
1105 SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = 58,
1106 SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = 59,
1107 SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = 60,
1108 SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = 61,
1109 SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = 63,
1110 SVGA3D_DEVCAP_SURFACEFMT_V16U16 = 65,
1111 SVGA3D_DEVCAP_SURFACEFMT_G16R16 = 66,
1112 SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67,
1113 SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68,
1114 SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69,
1115 SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = 70,
1116 SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = 71,
1117 SVGA3D_DEVCAP_ALPHATOCOVERAGE = 72,
1118 SVGA3D_DEVCAP_SUPERSAMPLE = 73,
1119 SVGA3D_DEVCAP_AUTOGENMIPMAPS = 74,
1120 SVGA3D_DEVCAP_SURFACEFMT_NV12 = 75,
1121 SVGA3D_DEVCAP_SURFACEFMT_AYUV = 76,
1122 SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = 79,
1123 SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = 80,
1124 SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = 81,
1125 SVGA3D_DEVCAP_SURFACEFMT_ATI1 = 82,
1126 SVGA3D_DEVCAP_SURFACEFMT_ATI2 = 83,
1127#endif
1128
1129 LogRel(("VMSVGA3d: Capabilities:\n"));
1130 LogRel(("VMSVGA3d: maxActiveLights=%-2d maxTextures=%-2d\n",
1131 pState->caps.maxActiveLights, pState->caps.maxTextures));
1132 LogRel(("VMSVGA3d: maxClipDistances=%-2d maxColorAttachments=%-2d maxClipDistances=%d\n",
1133 pState->caps.maxClipDistances, pState->caps.maxColorAttachments, pState->caps.maxClipDistances));
1134 LogRel(("VMSVGA3d: maxColorAttachments=%-2d maxTextureAnisotropy=%-2d maxRectangleTextureSize=%d\n",
1135 pState->caps.maxColorAttachments, pState->caps.maxTextureAnisotropy, pState->caps.maxRectangleTextureSize));
1136 LogRel(("VMSVGA3d: maxVertexShaderTemps=%-2d maxVertexShaderInstructions=%d maxFragmentShaderInstructions=%d\n",
1137 pState->caps.maxVertexShaderTemps, pState->caps.maxVertexShaderInstructions, pState->caps.maxFragmentShaderInstructions));
1138 LogRel(("VMSVGA3d: maxFragmentShaderTemps=%d flPointSize={%d.%02u, %d.%02u}\n",
1139 pState->caps.maxFragmentShaderTemps,
1140 (int)pState->caps.flPointSize[0], (int)(pState->caps.flPointSize[0] * 100) % 100,
1141 (int)pState->caps.flPointSize[1], (int)(pState->caps.flPointSize[1] * 100) % 100));
1142 LogRel(("VMSVGA3d: fragmentShaderVersion=%-2d vertexShaderVersion=%-2d\n",
1143 pState->caps.fragmentShaderVersion, pState->caps.vertexShaderVersion));
1144 LogRel(("VMSVGA3d: fS3TCSupported=%-2d fTextureFilterAnisotropicSupported=%d\n",
1145 pState->caps.fS3TCSupported, pState->caps.fTextureFilterAnisotropicSupported));
1146
1147
1148 /* Initialize the shader library. */
1149 pState->ShaderIf.pfnSwitchInitProfile = vmsvga3dShaderIfSwitchInitProfile;
1150 pState->ShaderIf.pfnGetNextExtension = vmsvga3dShaderIfGetNextExtension;
1151 rc = ShaderInitLib(&pState->ShaderIf);
1152 AssertRC(rc);
1153
1154 /* Cleanup */
1155 rc = vmsvga3dBackContextDestroy(pThisCC, 1);
1156 AssertRC(rc);
1157#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
1158 rc = vmsvga3dBackContextDestroy(pThisCC, 2);
1159 AssertRC(rc);
1160#endif
1161
1162 if ( pState->rsGLVersion < 3.0
1163 && pState->rsOtherGLVersion < 3.0 /* darwin: legacy profile hack */)
1164 {
1165 LogRel(("VMSVGA3d: unsupported OpenGL version; minimum is 3.0\n"));
1166 return VERR_NOT_IMPLEMENTED;
1167 }
1168
1169 return VINF_SUCCESS;
1170}
1171
1172static DECLCALLBACK(int) vmsvga3dBackReset(PVGASTATECC pThisCC)
1173{
1174 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1175 AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY);
1176
1177 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
1178 vmsvga3dContextDestroyOgl(pThisCC, &pState->SharedCtx, VMSVGA3D_SHARED_CTX_ID);
1179
1180 return VINF_SUCCESS;
1181}
1182
1183static DECLCALLBACK(int) vmsvga3dBackTerminate(PVGASTATECC pThisCC)
1184{
1185 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1186 AssertReturn(pState, VERR_WRONG_ORDER);
1187 int rc;
1188
1189 /* Terminate the shader library. */
1190 rc = ShaderDestroyLib();
1191 AssertRC(rc);
1192
1193#ifdef RT_OS_WINDOWS
1194 /* Terminate the window creation thread. */
1195 rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_EXIT, 0, 0);
1196 AssertRCReturn(rc, rc);
1197
1198 RTSemEventDestroy(pState->WndRequestSem);
1199#elif defined(RT_OS_DARWIN)
1200
1201#elif defined(RT_OS_LINUX)
1202 /* signal to the thread that it is supposed to exit */
1203 pState->bTerminate = true;
1204 /* wait for it to terminate */
1205 rc = RTThreadWait(pState->pWindowThread, 10000, NULL);
1206 AssertRC(rc);
1207 XCloseDisplay(pState->display);
1208#endif
1209
1210 RTStrFree(pState->pszExtensions);
1211 pState->pszExtensions = NULL;
1212#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
1213 RTStrFree(pState->pszOtherExtensions);
1214#endif
1215 pState->pszOtherExtensions = NULL;
1216
1217 return VINF_SUCCESS;
1218}
1219
1220
1221static DECLCALLBACK(void) vmsvga3dBackUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport)
1222{
1223 /** @todo Move the visible framebuffer content here, don't wait for the guest to
1224 * redraw it. */
1225
1226#ifdef RT_OS_DARWIN
1227 RT_NOREF(pOldViewport);
1228 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1229 if ( pState
1230 && idScreen == 0
1231 && pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
1232 {
1233 vmsvga3dCocoaViewUpdateViewport(pState->SharedCtx.cocoaView);
1234 }
1235#else
1236 RT_NOREF(pThisCC, idScreen, pOldViewport);
1237#endif
1238}
1239
1240
1241/**
1242 * Worker for vmsvga3dBackQueryCaps that figures out supported operations for a
1243 * given surface format capability.
1244 *
1245 * @returns Supported/indented operations (SVGA3DFORMAT_OP_XXX).
1246 * @param idx3dCaps The SVGA3D_CAPS_XXX value of the surface format.
1247 *
1248 * @remarks See fromat_cap_table in svga_format.c (mesa/gallium) for a reference
1249 * of implicit guest expectations:
1250 * http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/svga_format.c
1251 */
1252static uint32_t vmsvga3dGetSurfaceFormatSupport(uint32_t idx3dCaps)
1253{
1254 uint32_t result = 0;
1255
1256 /** @todo missing:
1257 *
1258 * SVGA3DFORMAT_OP_PIXELSIZE
1259 */
1260
1261 switch (idx3dCaps)
1262 {
1263 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1264 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
1265 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
1266 result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB
1267 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
1268 | SVGA3DFORMAT_OP_DISPLAYMODE /* Should not be set for alpha formats. */
1269 | SVGA3DFORMAT_OP_3DACCELERATION; /* implies OP_DISPLAYMODE */
1270 break;
1271
1272 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
1273 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
1274 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
1275 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
1276 result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB
1277 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
1278 | SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET;
1279 break;
1280 }
1281
1282 /** @todo check hardware caps! */
1283 switch (idx3dCaps)
1284 {
1285 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1286 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
1287 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
1288 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
1289 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
1290 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
1291 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
1292 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
1293 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
1294 case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
1295 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
1296 result |= SVGA3DFORMAT_OP_TEXTURE
1297 | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
1298 | SVGA3DFORMAT_OP_OFFSCREENPLAIN
1299 | SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
1300 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1301 | SVGA3DFORMAT_OP_CUBETEXTURE
1302 | SVGA3DFORMAT_OP_SRGBREAD
1303 | SVGA3DFORMAT_OP_SRGBWRITE;
1304 break;
1305
1306 case SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
1307 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
1308 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
1309 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
1310 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
1311 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
1312 result |= SVGA3DFORMAT_OP_ZSTENCIL
1313 | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
1314 | SVGA3DFORMAT_OP_TEXTURE /* Necessary for Ubuntu Unity */;
1315 break;
1316
1317 case SVGA3D_DEVCAP_SURFACEFMT_DXT1:
1318 case SVGA3D_DEVCAP_SURFACEFMT_DXT2:
1319 case SVGA3D_DEVCAP_SURFACEFMT_DXT3:
1320 case SVGA3D_DEVCAP_SURFACEFMT_DXT4:
1321 case SVGA3D_DEVCAP_SURFACEFMT_DXT5:
1322 result |= SVGA3DFORMAT_OP_TEXTURE
1323 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1324 | SVGA3DFORMAT_OP_CUBETEXTURE
1325 | SVGA3DFORMAT_OP_SRGBREAD;
1326 break;
1327
1328 case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
1329 case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
1330 case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
1331 case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
1332 case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
1333 break;
1334
1335 case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
1336 case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
1337 case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
1338 case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
1339 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
1340 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
1341 result |= SVGA3DFORMAT_OP_TEXTURE
1342 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1343 | SVGA3DFORMAT_OP_CUBETEXTURE
1344 | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
1345 break;
1346
1347 case SVGA3D_DEVCAP_SURFACEFMT_V16U16:
1348 case SVGA3D_DEVCAP_SURFACEFMT_G16R16:
1349 case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
1350 result |= SVGA3DFORMAT_OP_TEXTURE
1351 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1352 | SVGA3DFORMAT_OP_CUBETEXTURE
1353 | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
1354 break;
1355
1356 case SVGA3D_DEVCAP_SURFACEFMT_UYVY:
1357 case SVGA3D_DEVCAP_SURFACEFMT_YUY2:
1358 result |= SVGA3DFORMAT_OP_OFFSCREENPLAIN
1359 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
1360 | SVGA3DFORMAT_OP_TEXTURE;
1361 break;
1362
1363 case SVGA3D_DEVCAP_SURFACEFMT_NV12:
1364 case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */
1365 break;
1366 }
1367 Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result)));
1368
1369 return result;
1370}
1371
1372#if 0 /* unused */
1373static uint32_t vmsvga3dGetDepthFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps)
1374{
1375 RT_NOREF(pState3D, idx3dCaps);
1376
1377 /** @todo test this somehow */
1378 uint32_t result = SVGA3DFORMAT_OP_ZSTENCIL | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH;
1379
1380 Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result)));
1381 return result;
1382}
1383#endif
1384
1385
1386static DECLCALLBACK(int) vmsvga3dBackQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val)
1387{
1388 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1389 AssertReturn(pState, VERR_NO_MEMORY);
1390 int rc = VINF_SUCCESS;
1391
1392 *pu32Val = 0;
1393
1394 /*
1395 * The capabilities access by current (2015-03-01) linux sources (gallium,
1396 * vmwgfx, xorg-video-vmware) are annotated, caps without xref annotations
1397 * aren't access.
1398 */
1399
1400 switch (idx3dCaps)
1401 {
1402 /* Linux: vmwgfx_fifo.c in kmod; only used with SVGA_CAP_GBOBJECTS. */
1403 case SVGA3D_DEVCAP_3D:
1404 *pu32Val = 1; /* boolean? */
1405 break;
1406
1407 case SVGA3D_DEVCAP_MAX_LIGHTS:
1408 *pu32Val = pState->caps.maxActiveLights;
1409 break;
1410
1411 case SVGA3D_DEVCAP_MAX_TEXTURES:
1412 *pu32Val = pState->caps.maxTextures;
1413 break;
1414
1415 case SVGA3D_DEVCAP_MAX_CLIP_PLANES:
1416 *pu32Val = pState->caps.maxClipDistances;
1417 break;
1418
1419 /* Linux: svga_screen.c in gallium; 3.0 or later required. */
1420 case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
1421 *pu32Val = pState->caps.vertexShaderVersion;
1422 break;
1423
1424 case SVGA3D_DEVCAP_VERTEX_SHADER:
1425 /* boolean? */
1426 *pu32Val = (pState->caps.vertexShaderVersion != SVGA3DVSVERSION_NONE);
1427 break;
1428
1429 /* Linux: svga_screen.c in gallium; 3.0 or later required. */
1430 case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
1431 *pu32Val = pState->caps.fragmentShaderVersion;
1432 break;
1433
1434 case SVGA3D_DEVCAP_FRAGMENT_SHADER:
1435 /* boolean? */
1436 *pu32Val = (pState->caps.fragmentShaderVersion != SVGA3DPSVERSION_NONE);
1437 break;
1438
1439 case SVGA3D_DEVCAP_S23E8_TEXTURES:
1440 case SVGA3D_DEVCAP_S10E5_TEXTURES:
1441 /* Must be obsolete by now; surface format caps specify the same thing. */
1442 rc = VERR_INVALID_PARAMETER;
1443 break;
1444
1445 case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
1446 break;
1447
1448 /*
1449 * 2. The BUFFER_FORMAT capabilities are deprecated, and they always
1450 * return TRUE. Even on physical hardware that does not support
1451 * these formats natively, the SVGA3D device will provide an emulation
1452 * which should be invisible to the guest OS.
1453 */
1454 case SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
1455 case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
1456 case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
1457 *pu32Val = 1;
1458 break;
1459
1460 case SVGA3D_DEVCAP_QUERY_TYPES:
1461 break;
1462
1463 case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
1464 break;
1465
1466 /* Linux: svga_screen.c in gallium; capped at 80.0, default 1.0. */
1467 case SVGA3D_DEVCAP_MAX_POINT_SIZE:
1468 AssertCompile(sizeof(uint32_t) == sizeof(float));
1469 *(float *)pu32Val = pState->caps.flPointSize[1];
1470 break;
1471
1472 case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
1473 /** @todo ?? */
1474 rc = VERR_INVALID_PARAMETER;
1475 break;
1476
1477 /* Linux: svga_screen.c in gallium (for PIPE_CAP_MAX_TEXTURE_2D_LEVELS); have default if missing. */
1478 case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
1479 case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
1480 *pu32Val = pState->caps.maxRectangleTextureSize;
1481 break;
1482
1483 /* Linux: svga_screen.c in gallium (for PIPE_CAP_MAX_TEXTURE_3D_LEVELS); have default if missing. */
1484 case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
1485 //*pu32Val = pCaps->MaxVolumeExtent;
1486 *pu32Val = 256;
1487 break;
1488
1489 case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
1490 *pu32Val = 32768; /* hardcoded in Wine */
1491 break;
1492
1493 case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
1494 //*pu32Val = pCaps->MaxTextureAspectRatio;
1495 break;
1496
1497 /* Linux: svga_screen.c in gallium (for PIPE_CAPF_MAX_TEXTURE_ANISOTROPY); defaults to 4.0. */
1498 case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
1499 *pu32Val = pState->caps.maxTextureAnisotropy;
1500 break;
1501
1502 case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
1503 case SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
1504 *pu32Val = 0xFFFFF; /* hardcoded in Wine */
1505 break;
1506
1507 /* Linux: svga_screen.c in gallium (for PIPE_SHADER_VERTEX/PIPE_SHADER_CAP_MAX_INSTRUCTIONS); defaults to 512. */
1508 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
1509 *pu32Val = pState->caps.maxVertexShaderInstructions;
1510 break;
1511
1512 case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
1513 *pu32Val = pState->caps.maxFragmentShaderInstructions;
1514 break;
1515
1516 /* Linux: svga_screen.c in gallium (for PIPE_SHADER_VERTEX/PIPE_SHADER_CAP_MAX_TEMPS); defaults to 32. */
1517 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
1518 *pu32Val = pState->caps.maxVertexShaderTemps;
1519 break;
1520
1521 /* Linux: svga_screen.c in gallium (for PIPE_SHADER_FRAGMENT/PIPE_SHADER_CAP_MAX_TEMPS); defaults to 32. */
1522 case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
1523 *pu32Val = pState->caps.maxFragmentShaderTemps;
1524 break;
1525
1526 case SVGA3D_DEVCAP_TEXTURE_OPS:
1527 break;
1528
1529 case SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */
1530 break;
1531
1532 case SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */
1533 break;
1534
1535 case SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */
1536 break;
1537
1538 case SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */
1539 break;
1540
1541 case SVGA3D_DEVCAP_AUTOGENMIPMAPS:
1542 //*pu32Val = !!(pCaps->Caps2 & D3DCAPS2_CANAUTOGENMIPMAP);
1543 break;
1544
1545 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
1546 break;
1547
1548 case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: /** @todo same thing? */
1549 case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
1550 *pu32Val = pState->caps.maxColorAttachments;
1551 break;
1552
1553 /*
1554 * This is the maximum number of SVGA context IDs that the guest
1555 * can define using SVGA_3D_CMD_CONTEXT_DEFINE.
1556 */
1557 case SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
1558 *pu32Val = SVGA3D_MAX_CONTEXT_IDS;
1559 break;
1560
1561 /*
1562 * This is the maximum number of SVGA surface IDs that the guest
1563 * can define using SVGA_3D_CMD_SURFACE_DEFINE*.
1564 */
1565 case SVGA3D_DEVCAP_MAX_SURFACE_IDS:
1566 *pu32Val = SVGA3D_MAX_SURFACE_IDS;
1567 break;
1568
1569#if 0 /* Appeared more recently, not yet implemented. */
1570 /* Linux: svga_screen.c in gallium; defaults to FALSE. */
1571 case SVGA3D_DEVCAP_LINE_AA:
1572 break;
1573 /* Linux: svga_screen.c in gallium; defaults to FALSE. */
1574 case SVGA3D_DEVCAP_LINE_STIPPLE:
1575 break;
1576 /* Linux: svga_screen.c in gallium; defaults to 1.0. */
1577 case SVGA3D_DEVCAP_MAX_LINE_WIDTH:
1578 break;
1579 /* Linux: svga_screen.c in gallium; defaults to 1.0. */
1580 case SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH:
1581 break;
1582#endif
1583
1584 /*
1585 * Supported surface formats.
1586 * Linux: svga_format.c in gallium, format_cap_table defines implicit expectations.
1587 */
1588 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1589 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
1590 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
1591 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
1592 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
1593 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
1594 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
1595 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
1596 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
1597 case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
1598 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
1599 case SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
1600 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
1601 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
1602 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
1603 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
1604 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
1605 case SVGA3D_DEVCAP_SURFACEFMT_DXT1:
1606 *pu32Val = vmsvga3dGetSurfaceFormatSupport(idx3dCaps);
1607 break;
1608
1609 case SVGA3D_DEVCAP_SURFACEFMT_DXT2:
1610 case SVGA3D_DEVCAP_SURFACEFMT_DXT3:
1611 case SVGA3D_DEVCAP_SURFACEFMT_DXT4:
1612 case SVGA3D_DEVCAP_SURFACEFMT_DXT5:
1613 case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
1614 case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
1615 case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
1616 case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
1617 case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
1618 case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
1619 case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
1620 case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
1621 case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
1622 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
1623 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
1624 case SVGA3D_DEVCAP_SURFACEFMT_V16U16:
1625 case SVGA3D_DEVCAP_SURFACEFMT_G16R16:
1626 case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
1627 case SVGA3D_DEVCAP_SURFACEFMT_UYVY:
1628 case SVGA3D_DEVCAP_SURFACEFMT_YUY2:
1629 case SVGA3D_DEVCAP_SURFACEFMT_NV12:
1630 case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */
1631 *pu32Val = vmsvga3dGetSurfaceFormatSupport(idx3dCaps);
1632 break;
1633
1634 /* Linux: Not referenced in current sources. */
1635 case SVGA3D_DEVCAP_SURFACEFMT_ATI1:
1636 case SVGA3D_DEVCAP_SURFACEFMT_ATI2:
1637 Log(("CAPS: Unknown CAP %s\n", vmsvga3dGetCapString(idx3dCaps)));
1638 rc = VERR_INVALID_PARAMETER;
1639 *pu32Val = 0;
1640 break;
1641
1642 default:
1643 Log(("CAPS: Unexpected CAP %d\n", idx3dCaps));
1644 rc = VERR_INVALID_PARAMETER;
1645 break;
1646 }
1647
1648 Log(("CAPS: %s - %x\n", vmsvga3dGetCapString(idx3dCaps), *pu32Val));
1649 return rc;
1650}
1651
1652/**
1653 * Convert SVGA format value to its OpenGL equivalent
1654 *
1655 * @remarks Clues to be had in format_texture_info table (wined3d/utils.c) with
1656 * help from wined3dformat_from_d3dformat().
1657 */
1658void vmsvga3dSurfaceFormat2OGL(PVMSVGA3DSURFACE pSurface, SVGA3dSurfaceFormat format)
1659{
1660#if 0
1661#define AssertTestFmt(f) AssertMsgFailed(("Test me - " #f "\n"))
1662#else
1663#define AssertTestFmt(f) do {} while(0)
1664#endif
1665 /* Init cbBlockGL for non-emulated formats. */
1666 pSurface->cbBlockGL = pSurface->cbBlock;
1667
1668 switch (format)
1669 {
1670 case SVGA3D_X8R8G8B8: /* D3DFMT_X8R8G8B8 - WINED3DFMT_B8G8R8X8_UNORM */
1671 pSurface->internalFormatGL = GL_RGB8;
1672 pSurface->formatGL = GL_BGRA;
1673 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1674 break;
1675 case SVGA3D_A8R8G8B8: /* D3DFMT_A8R8G8B8 - WINED3DFMT_B8G8R8A8_UNORM */
1676 pSurface->internalFormatGL = GL_RGBA8;
1677 pSurface->formatGL = GL_BGRA;
1678 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1679 break;
1680 case SVGA3D_R5G6B5: /* D3DFMT_R5G6B5 - WINED3DFMT_B5G6R5_UNORM */
1681 pSurface->internalFormatGL = GL_RGB5;
1682 pSurface->formatGL = GL_RGB;
1683 pSurface->typeGL = GL_UNSIGNED_SHORT_5_6_5;
1684 AssertTestFmt(SVGA3D_R5G6B5);
1685 break;
1686 case SVGA3D_X1R5G5B5: /* D3DFMT_X1R5G5B5 - WINED3DFMT_B5G5R5X1_UNORM */
1687 pSurface->internalFormatGL = GL_RGB5;
1688 pSurface->formatGL = GL_BGRA;
1689 pSurface->typeGL = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1690 AssertTestFmt(SVGA3D_X1R5G5B5);
1691 break;
1692 case SVGA3D_A1R5G5B5: /* D3DFMT_A1R5G5B5 - WINED3DFMT_B5G5R5A1_UNORM */
1693 pSurface->internalFormatGL = GL_RGB5_A1;
1694 pSurface->formatGL = GL_BGRA;
1695 pSurface->typeGL = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1696 AssertTestFmt(SVGA3D_A1R5G5B5);
1697 break;
1698 case SVGA3D_A4R4G4B4: /* D3DFMT_A4R4G4B4 - WINED3DFMT_B4G4R4A4_UNORM */
1699 pSurface->internalFormatGL = GL_RGBA4;
1700 pSurface->formatGL = GL_BGRA;
1701 pSurface->typeGL = GL_UNSIGNED_SHORT_4_4_4_4_REV;
1702 AssertTestFmt(SVGA3D_A4R4G4B4);
1703 break;
1704
1705 case SVGA3D_R8G8B8A8_UNORM:
1706 pSurface->internalFormatGL = GL_RGBA8;
1707 pSurface->formatGL = GL_RGBA;
1708 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1709 break;
1710
1711 case SVGA3D_Z_D32: /* D3DFMT_D32 - WINED3DFMT_D32_UNORM */
1712 pSurface->internalFormatGL = GL_DEPTH_COMPONENT32;
1713 pSurface->formatGL = GL_DEPTH_COMPONENT;
1714 pSurface->typeGL = GL_UNSIGNED_INT;
1715 break;
1716 case SVGA3D_Z_D16: /* D3DFMT_D16 - WINED3DFMT_D16_UNORM */
1717 pSurface->internalFormatGL = GL_DEPTH_COMPONENT16; /** @todo Wine suggests GL_DEPTH_COMPONENT24. */
1718 pSurface->formatGL = GL_DEPTH_COMPONENT;
1719 pSurface->typeGL = GL_UNSIGNED_SHORT;
1720 AssertTestFmt(SVGA3D_Z_D16);
1721 break;
1722 case SVGA3D_Z_D24S8: /* D3DFMT_D24S8 - WINED3DFMT_D24_UNORM_S8_UINT */
1723 pSurface->internalFormatGL = GL_DEPTH24_STENCIL8;
1724 pSurface->formatGL = GL_DEPTH_STENCIL;
1725 pSurface->typeGL = GL_UNSIGNED_INT_24_8;
1726 break;
1727 case SVGA3D_Z_D15S1: /* D3DFMT_D15S1 - WINED3DFMT_S1_UINT_D15_UNORM */
1728 pSurface->internalFormatGL = GL_DEPTH_COMPONENT16; /** @todo ??? */
1729 pSurface->formatGL = GL_DEPTH_STENCIL;
1730 pSurface->typeGL = GL_UNSIGNED_SHORT;
1731 /** @todo Wine sources hints at no hw support for this, so test this one! */
1732 AssertTestFmt(SVGA3D_Z_D15S1);
1733 break;
1734 case SVGA3D_Z_D24X8: /* D3DFMT_D24X8 - WINED3DFMT_X8D24_UNORM */
1735 pSurface->internalFormatGL = GL_DEPTH_COMPONENT24;
1736 pSurface->formatGL = GL_DEPTH_COMPONENT;
1737 pSurface->typeGL = GL_UNSIGNED_INT;
1738 AssertTestFmt(SVGA3D_Z_D24X8);
1739 break;
1740
1741 /* Advanced D3D9 depth formats. */
1742 case SVGA3D_Z_DF16: /* D3DFMT_DF16? - not supported */
1743 pSurface->internalFormatGL = GL_DEPTH_COMPONENT16;
1744 pSurface->formatGL = GL_DEPTH_COMPONENT;
1745 pSurface->typeGL = GL_HALF_FLOAT;
1746 break;
1747
1748 case SVGA3D_Z_DF24: /* D3DFMT_DF24? - not supported */
1749 pSurface->internalFormatGL = GL_DEPTH_COMPONENT24;
1750 pSurface->formatGL = GL_DEPTH_COMPONENT;
1751 pSurface->typeGL = GL_FLOAT; /* ??? */
1752 break;
1753
1754 case SVGA3D_Z_D24S8_INT: /* D3DFMT_D24S8 */
1755 pSurface->internalFormatGL = GL_DEPTH24_STENCIL8;
1756 pSurface->formatGL = GL_DEPTH_STENCIL;
1757 pSurface->typeGL = GL_UNSIGNED_INT_24_8;
1758 break;
1759
1760 case SVGA3D_DXT1: /* D3DFMT_DXT1 - WINED3DFMT_DXT1 */
1761 pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1762 pSurface->formatGL = GL_RGBA; /* not used */
1763 pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */
1764 break;
1765
1766 case SVGA3D_DXT2: /* D3DFMT_DXT2 */
1767 /* "DXT2 and DXT3 are the same from an API perspective." */
1768 RT_FALL_THRU();
1769 case SVGA3D_DXT3: /* D3DFMT_DXT3 - WINED3DFMT_DXT3 */
1770 pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
1771 pSurface->formatGL = GL_RGBA; /* not used */
1772 pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */
1773 break;
1774
1775 case SVGA3D_DXT4: /* D3DFMT_DXT4 */
1776 /* "DXT4 and DXT5 are the same from an API perspective." */
1777 RT_FALL_THRU();
1778 case SVGA3D_DXT5: /* D3DFMT_DXT5 - WINED3DFMT_DXT5 */
1779 pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
1780 pSurface->formatGL = GL_RGBA; /* not used */
1781 pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */
1782 break;
1783
1784 case SVGA3D_LUMINANCE8: /* D3DFMT_? - ? */
1785 pSurface->internalFormatGL = GL_LUMINANCE8_EXT;
1786 pSurface->formatGL = GL_LUMINANCE;
1787 pSurface->typeGL = GL_UNSIGNED_BYTE;
1788 break;
1789
1790 case SVGA3D_LUMINANCE16: /* D3DFMT_? - ? */
1791 pSurface->internalFormatGL = GL_LUMINANCE16_EXT;
1792 pSurface->formatGL = GL_LUMINANCE;
1793 pSurface->typeGL = GL_UNSIGNED_SHORT;
1794 break;
1795
1796 case SVGA3D_LUMINANCE4_ALPHA4: /* D3DFMT_? - ? */
1797 pSurface->internalFormatGL = GL_LUMINANCE4_ALPHA4_EXT;
1798 pSurface->formatGL = GL_LUMINANCE_ALPHA;
1799 pSurface->typeGL = GL_UNSIGNED_BYTE;
1800 break;
1801
1802 case SVGA3D_LUMINANCE8_ALPHA8: /* D3DFMT_? - ? */
1803 pSurface->internalFormatGL = GL_LUMINANCE8_ALPHA8_EXT;
1804 pSurface->formatGL = GL_LUMINANCE_ALPHA;
1805 pSurface->typeGL = GL_UNSIGNED_BYTE; /* unsigned_short causes issues even though this type should be 16-bit */
1806 break;
1807
1808 case SVGA3D_ALPHA8: /* D3DFMT_A8? - WINED3DFMT_A8_UNORM? */
1809 pSurface->internalFormatGL = GL_ALPHA8_EXT;
1810 pSurface->formatGL = GL_ALPHA;
1811 pSurface->typeGL = GL_UNSIGNED_BYTE;
1812 break;
1813
1814#if 0
1815
1816 /* Bump-map formats */
1817 case SVGA3D_BUMPU8V8:
1818 return D3DFMT_V8U8;
1819 case SVGA3D_BUMPL6V5U5:
1820 return D3DFMT_L6V5U5;
1821 case SVGA3D_BUMPX8L8V8U8:
1822 return D3DFMT_X8L8V8U8;
1823 case SVGA3D_FORMAT_DEAD1:
1824 /* No corresponding D3D9 equivalent. */
1825 AssertFailedReturn(D3DFMT_UNKNOWN);
1826 /* signed bump-map formats */
1827 case SVGA3D_V8U8:
1828 return D3DFMT_V8U8;
1829 case SVGA3D_Q8W8V8U8:
1830 return D3DFMT_Q8W8V8U8;
1831 case SVGA3D_CxV8U8:
1832 return D3DFMT_CxV8U8;
1833 /* mixed bump-map formats */
1834 case SVGA3D_X8L8V8U8:
1835 return D3DFMT_X8L8V8U8;
1836 case SVGA3D_A2W10V10U10:
1837 return D3DFMT_A2W10V10U10;
1838#endif
1839
1840 case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */ /* D3DFMT_A16B16G16R16F - WINED3DFMT_R16G16B16A16_FLOAT */
1841 pSurface->internalFormatGL = GL_RGBA16F;
1842 pSurface->formatGL = GL_RGBA;
1843#if 0 /* bird: wine uses half float, sounds correct to me... */
1844 pSurface->typeGL = GL_FLOAT;
1845#else
1846 pSurface->typeGL = GL_HALF_FLOAT;
1847 AssertTestFmt(SVGA3D_ARGB_S10E5);
1848#endif
1849 break;
1850
1851 case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */ /* D3DFMT_A32B32G32R32F - WINED3DFMT_R32G32B32A32_FLOAT */
1852 pSurface->internalFormatGL = GL_RGBA32F;
1853 pSurface->formatGL = GL_RGBA;
1854 pSurface->typeGL = GL_FLOAT; /* ?? - same as wine, so probably correct */
1855 break;
1856
1857 case SVGA3D_A2R10G10B10: /* D3DFMT_A2R10G10B10 - WINED3DFMT_B10G10R10A2_UNORM */
1858 pSurface->internalFormatGL = GL_RGB10_A2; /* ?? - same as wine, so probably correct */
1859#if 0 /* bird: Wine uses GL_BGRA instead of GL_RGBA. */
1860 pSurface->formatGL = GL_RGBA;
1861#else
1862 pSurface->formatGL = GL_BGRA;
1863#endif
1864 pSurface->typeGL = GL_UNSIGNED_INT;
1865 AssertTestFmt(SVGA3D_A2R10G10B10);
1866 break;
1867
1868
1869 /* Single- and dual-component floating point formats */
1870 case SVGA3D_R_S10E5: /* D3DFMT_R16F - WINED3DFMT_R16_FLOAT */
1871 pSurface->internalFormatGL = GL_R16F;
1872 pSurface->formatGL = GL_RED;
1873#if 0 /* bird: wine uses half float, sounds correct to me... */
1874 pSurface->typeGL = GL_FLOAT;
1875#else
1876 pSurface->typeGL = GL_HALF_FLOAT;
1877 AssertTestFmt(SVGA3D_R_S10E5);
1878#endif
1879 break;
1880 case SVGA3D_R_S23E8: /* D3DFMT_R32F - WINED3DFMT_R32_FLOAT */
1881 pSurface->internalFormatGL = GL_R32F;
1882 pSurface->formatGL = GL_RED;
1883 pSurface->typeGL = GL_FLOAT;
1884 break;
1885 case SVGA3D_RG_S10E5: /* D3DFMT_G16R16F - WINED3DFMT_R16G16_FLOAT */
1886 pSurface->internalFormatGL = GL_RG16F;
1887 pSurface->formatGL = GL_RG;
1888#if 0 /* bird: wine uses half float, sounds correct to me... */
1889 pSurface->typeGL = GL_FLOAT;
1890#else
1891 pSurface->typeGL = GL_HALF_FLOAT;
1892 AssertTestFmt(SVGA3D_RG_S10E5);
1893#endif
1894 break;
1895 case SVGA3D_RG_S23E8: /* D3DFMT_G32R32F - WINED3DFMT_R32G32_FLOAT */
1896 pSurface->internalFormatGL = GL_RG32F;
1897 pSurface->formatGL = GL_RG;
1898 pSurface->typeGL = GL_FLOAT;
1899 break;
1900
1901 /*
1902 * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
1903 * the most efficient format to use when creating new surfaces
1904 * expressly for index or vertex data.
1905 */
1906 case SVGA3D_BUFFER:
1907 pSurface->internalFormatGL = -1;
1908 pSurface->formatGL = -1;
1909 pSurface->typeGL = -1;
1910 break;
1911
1912#if 0
1913 return D3DFMT_UNKNOWN;
1914
1915 case SVGA3D_V16U16:
1916 return D3DFMT_V16U16;
1917#endif
1918
1919 case SVGA3D_G16R16: /* D3DFMT_G16R16 - WINED3DFMT_R16G16_UNORM */
1920 pSurface->internalFormatGL = GL_RG16;
1921 pSurface->formatGL = GL_RG;
1922#if 0 /* bird: Wine uses GL_UNSIGNED_SHORT here. */
1923 pSurface->typeGL = GL_UNSIGNED_INT;
1924#else
1925 pSurface->typeGL = GL_UNSIGNED_SHORT;
1926 AssertTestFmt(SVGA3D_G16R16);
1927#endif
1928 break;
1929
1930 case SVGA3D_A16B16G16R16: /* D3DFMT_A16B16G16R16 - WINED3DFMT_R16G16B16A16_UNORM */
1931 pSurface->internalFormatGL = GL_RGBA16;
1932 pSurface->formatGL = GL_RGBA;
1933#if 0 /* bird: Wine uses GL_UNSIGNED_SHORT here. */
1934 pSurface->typeGL = GL_UNSIGNED_INT; /* ??? */
1935#else
1936 pSurface->typeGL = GL_UNSIGNED_SHORT;
1937 AssertTestFmt(SVGA3D_A16B16G16R16);
1938#endif
1939 break;
1940
1941 case SVGA3D_R8G8B8A8_SNORM:
1942 pSurface->internalFormatGL = GL_RGB8;
1943 pSurface->formatGL = GL_BGRA;
1944 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1945 AssertTestFmt(SVGA3D_R8G8B8A8_SNORM);
1946 break;
1947 case SVGA3D_R16G16_UNORM:
1948 pSurface->internalFormatGL = GL_RG16;
1949 pSurface->formatGL = GL_RG;
1950 pSurface->typeGL = GL_UNSIGNED_SHORT;
1951 AssertTestFmt(SVGA3D_R16G16_UNORM);
1952 break;
1953
1954 /* Packed Video formats */
1955 case SVGA3D_UYVY:
1956 case SVGA3D_YUY2:
1957 /* Use a BRGA texture to hold the data and convert it to an actual BGRA. */
1958 pSurface->fEmulated = true;
1959 pSurface->internalFormatGL = GL_RGBA8;
1960 pSurface->formatGL = GL_BGRA;
1961 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1962 pSurface->cbBlockGL = 4 * pSurface->cxBlock * pSurface->cyBlock;
1963 break;
1964
1965#if 0
1966 /* Planar video formats */
1967 case SVGA3D_NV12:
1968 return (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2');
1969
1970 /* Video format with alpha */
1971 case SVGA3D_FORMAT_DEAD2: /* Old SVGA3D_AYUV */
1972
1973 case SVGA3D_ATI1:
1974 case SVGA3D_ATI2:
1975 /* Unknown; only in DX10 & 11 */
1976 break;
1977#endif
1978 default:
1979 AssertMsgFailed(("Unsupported format %d\n", format));
1980 break;
1981 }
1982#undef AssertTestFmt
1983}
1984
1985
1986#if 0
1987/**
1988 * Convert SVGA multi sample count value to its D3D equivalent
1989 */
1990D3DMULTISAMPLE_TYPE vmsvga3dMultipeSampleCount2D3D(uint32_t multisampleCount)
1991{
1992 AssertCompile(D3DMULTISAMPLE_2_SAMPLES == 2);
1993 AssertCompile(D3DMULTISAMPLE_16_SAMPLES == 16);
1994
1995 if (multisampleCount > 16)
1996 return D3DMULTISAMPLE_NONE;
1997
1998 /** @todo exact same mapping as d3d? */
1999 return (D3DMULTISAMPLE_TYPE)multisampleCount;
2000}
2001#endif
2002
2003/**
2004 * Destroy backend specific surface bits (part of SVGA_3D_CMD_SURFACE_DESTROY).
2005 *
2006 * @param pThisCC The device state.
2007 * @param fClearCOTableEntry Not relevant for this backend.
2008 * @param pSurface The surface being destroyed.
2009 */
2010static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, bool fClearCOTableEntry, PVMSVGA3DSURFACE pSurface)
2011{
2012 RT_NOREF(fClearCOTableEntry);
2013
2014 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
2015 AssertReturnVoid(pState);
2016
2017 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
2018 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
2019
2020 switch (pSurface->enmOGLResType)
2021 {
2022 case VMSVGA3D_OGLRESTYPE_BUFFER:
2023 Assert(pSurface->oglId.buffer != OPENGL_INVALID_ID);
2024 pState->ext.glDeleteBuffers(1, &pSurface->oglId.buffer);
2025 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2026 break;
2027
2028 case VMSVGA3D_OGLRESTYPE_TEXTURE:
2029 Assert(pSurface->oglId.texture != OPENGL_INVALID_ID);
2030 glDeleteTextures(1, &pSurface->oglId.texture);
2031 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2032 if (pSurface->fEmulated)
2033 {
2034 if (pSurface->idEmulated)
2035 {
2036 glDeleteTextures(1, &pSurface->idEmulated);
2037 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2038 }
2039 }
2040 else
2041 {
2042 Assert(!pSurface->idEmulated);
2043 }
2044 break;
2045
2046 case VMSVGA3D_OGLRESTYPE_RENDERBUFFER:
2047 Assert(pSurface->oglId.renderbuffer != OPENGL_INVALID_ID);
2048 pState->ext.glDeleteRenderbuffers(1, &pSurface->oglId.renderbuffer);
2049 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2050 break;
2051
2052 default:
2053 AssertMsg(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface),
2054 ("hint=%#x, type=%d\n",
2055 (pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK), pSurface->enmOGLResType));
2056 break;
2057 }
2058}
2059
2060
2061static DECLCALLBACK(void) vmsvga3dBackSurfaceInvalidateImage(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface, uint32_t uFace, uint32_t uMipmap)
2062{
2063 RT_NOREF(pThisCC, pSurface, uFace, uMipmap);
2064}
2065
2066
2067static DECLCALLBACK(int) vmsvga3dBackSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src,
2068 uint32_t cCopyBoxes, SVGA3dCopyBox *pBox)
2069{
2070 int rc;
2071
2072 LogFunc(("Copy %d boxes from sid=%u face=%u mipmap=%u to sid=%u face=%u mipmap=%u\n",
2073 cCopyBoxes, src.sid, src.face, src.mipmap, dest.sid, dest.face, dest.mipmap));
2074
2075 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
2076 AssertReturn(pState, VERR_INVALID_STATE);
2077
2078 PVMSVGA3DSURFACE pSurfaceSrc;
2079 rc = vmsvga3dSurfaceFromSid(pState, src.sid, &pSurfaceSrc);
2080 AssertRCReturn(rc, rc);
2081
2082 PVMSVGA3DSURFACE pSurfaceDst;
2083 rc = vmsvga3dSurfaceFromSid(pState, dest.sid, &pSurfaceDst);
2084 AssertRCReturn(rc, rc);
2085
2086 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurfaceSrc))
2087 {
2088 /* The source surface is still in memory. */
2089 PVMSVGA3DMIPMAPLEVEL pMipmapLevelSrc;
2090 rc = vmsvga3dMipmapLevel(pSurfaceSrc, src.face, src.mipmap, &pMipmapLevelSrc);
2091 AssertRCReturn(rc, rc);
2092
2093 PVMSVGA3DMIPMAPLEVEL pMipmapLevelDst;
2094 rc = vmsvga3dMipmapLevel(pSurfaceDst, dest.face, dest.mipmap, &pMipmapLevelDst);
2095 AssertRCReturn(rc, rc);
2096
2097 /* The copy operation is performed on the shared context. */
2098 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
2099 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
2100
2101 /* Use glTexSubImage to upload the data to the destination texture.
2102 * The latter must be an OpenGL texture.
2103 */
2104 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurfaceDst))
2105 {
2106 LogFunc(("dest sid=%u type=0x%x format=%d -> create texture\n", dest.sid, pSurfaceDst->f.s.surface1Flags, pSurfaceDst->format));
2107 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, pContext->id, pSurfaceDst);
2108 AssertRCReturn(rc, rc);
2109 }
2110
2111 GLenum target;
2112 if (pSurfaceDst->targetGL == GL_TEXTURE_CUBE_MAP)
2113 target = vmsvga3dCubemapFaceFromIndex(dest.face);
2114 else
2115 {
2116 AssertMsg(pSurfaceDst->targetGL == GL_TEXTURE_2D, ("Test %#x\n", pSurfaceDst->targetGL));
2117 target = pSurfaceDst->targetGL;
2118 }
2119
2120 /* Save the unpacking parameters and set what we need here. */
2121 VMSVGAPACKPARAMS SavedParams;
2122 vmsvga3dOglSetUnpackParams(pState, pContext,
2123 pMipmapLevelSrc->mipmapSize.width,
2124 target == GL_TEXTURE_3D ? pMipmapLevelSrc->mipmapSize.height : 0,
2125 &SavedParams);
2126
2127 glBindTexture(pSurfaceDst->targetGL, pSurfaceDst->oglId.texture);
2128 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2129
2130 for (uint32_t i = 0; i < cCopyBoxes; ++i)
2131 {
2132 SVGA3dCopyBox clipBox = pBox[i];
2133 vmsvgaR3ClipCopyBox(&pMipmapLevelSrc->mipmapSize, &pMipmapLevelDst->mipmapSize, &clipBox);
2134 if ( !clipBox.w
2135 || !clipBox.h
2136 || !clipBox.d)
2137 {
2138 LogFunc(("Skipped empty box.\n"));
2139 continue;
2140 }
2141
2142 LogFunc(("copy box %d,%d,%d %dx%d to %d,%d,%d\n",
2143 clipBox.srcx, clipBox.srcy, clipBox.srcz, clipBox.w, clipBox.h, clipBox.x, clipBox.y, clipBox.z));
2144
2145 uint32_t const u32BlockX = clipBox.srcx / pSurfaceSrc->cxBlock;
2146 uint32_t const u32BlockY = clipBox.srcy / pSurfaceSrc->cyBlock;
2147 uint32_t const u32BlockZ = clipBox.srcz;
2148 Assert(u32BlockX * pSurfaceSrc->cxBlock == clipBox.srcx);
2149 Assert(u32BlockY * pSurfaceSrc->cyBlock == clipBox.srcy);
2150
2151 uint8_t const *pSrcBits = (uint8_t *)pMipmapLevelSrc->pSurfaceData
2152 + pMipmapLevelSrc->cbSurfacePlane * u32BlockZ
2153 + pMipmapLevelSrc->cbSurfacePitch * u32BlockY
2154 + pSurfaceSrc->cbBlock * u32BlockX;
2155
2156 if (target == GL_TEXTURE_3D)
2157 {
2158 if ( pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2159 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2160 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2161 {
2162 uint32_t const cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock;
2163 uint32_t const cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock;
2164 uint32_t const imageSize = cBlocksX * cBlocksY * clipBox.d * pSurfaceSrc->cbBlock;
2165 pState->ext.glCompressedTexSubImage3D(target, dest.mipmap,
2166 clipBox.x, clipBox.y, clipBox.z,
2167 clipBox.w, clipBox.h, clipBox.d,
2168 pSurfaceSrc->internalFormatGL, (GLsizei)imageSize, pSrcBits);
2169 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2170 }
2171 else
2172 {
2173 pState->ext.glTexSubImage3D(target, dest.mipmap,
2174 clipBox.x, clipBox.y, clipBox.z,
2175 clipBox.w, clipBox.h, clipBox.d,
2176 pSurfaceSrc->formatGL, pSurfaceSrc->typeGL, pSrcBits);
2177 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2178 }
2179 }
2180 else
2181 {
2182 if ( pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2183 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2184 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2185 {
2186 uint32_t const cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock;
2187 uint32_t const cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock;
2188 uint32_t const imageSize = cBlocksX * cBlocksY * pSurfaceSrc->cbBlock;
2189 pState->ext.glCompressedTexSubImage2D(target, dest.mipmap,
2190 clipBox.x, clipBox.y, clipBox.w, clipBox.h,
2191 pSurfaceSrc->internalFormatGL, (GLsizei)imageSize, pSrcBits);
2192 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2193 }
2194 else
2195 {
2196 glTexSubImage2D(target, dest.mipmap,
2197 clipBox.x, clipBox.y, clipBox.w, clipBox.h,
2198 pSurfaceSrc->formatGL, pSurfaceSrc->typeGL, pSrcBits);
2199 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2200 }
2201 }
2202 }
2203
2204 glBindTexture(pSurfaceDst->targetGL, 0);
2205 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2206
2207 vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams);
2208
2209 return VINF_SUCCESS;
2210 }
2211
2212 PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
2213 for (uint32_t i = 0; i < cCopyBoxes; i++)
2214 {
2215 SVGA3dBox destBox, srcBox;
2216
2217 srcBox.x = pBox[i].srcx;
2218 srcBox.y = pBox[i].srcy;
2219 srcBox.z = pBox[i].srcz;
2220 srcBox.w = pBox[i].w;
2221 srcBox.h = pBox[i].h;
2222 srcBox.d = pBox[i].d;
2223
2224 destBox.x = pBox[i].x;
2225 destBox.y = pBox[i].y;
2226 destBox.z = pBox[i].z;
2227 destBox.w = pBox[i].w;
2228 destBox.h = pBox[i].h;
2229 destBox.d = pBox[i].d;
2230
2231 /* No stretching is required, therefore use SVGA3D_STRETCH_BLT_POINT which translated to GL_NEAREST. */
2232 rc = vmsvga3dSurfaceStretchBlt(pThis, pThisCC, &dest, &destBox, &src, &srcBox, SVGA3D_STRETCH_BLT_POINT);
2233 AssertRCReturn(rc, rc);
2234 }
2235 return VINF_SUCCESS;
2236}
2237
2238
2239/**
2240 * Saves texture unpacking parameters and loads the specified ones.
2241 *
2242 * @param pState The VMSVGA3D state structure.
2243 * @param pContext The active context.
2244 * @param cxRow The number of pixels in a row. 0 for the entire width.
2245 * @param cyImage The height of the image in pixels. 0 for the entire height.
2246 * @param pSave Where to save stuff.
2247 */
2248void vmsvga3dOglSetUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, GLint cxRow, GLint cyImage,
2249 PVMSVGAPACKPARAMS pSave)
2250{
2251 RT_NOREF(pState);
2252
2253 /*
2254 * Save (ignore errors, setting the defaults we want and avoids restore).
2255 */
2256 pSave->iAlignment = 1;
2257 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_ALIGNMENT, &pSave->iAlignment), pState, pContext);
2258 pSave->cxRow = 0;
2259 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_ROW_LENGTH, &pSave->cxRow), pState, pContext);
2260 pSave->cyImage = 0;
2261 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &pSave->cyImage), pState, pContext);
2262
2263#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2264 pSave->fSwapBytes = GL_FALSE;
2265 glGetBooleanv(GL_UNPACK_SWAP_BYTES, &pSave->fSwapBytes);
2266 Assert(pSave->fSwapBytes == GL_FALSE);
2267
2268 pSave->fLsbFirst = GL_FALSE;
2269 glGetBooleanv(GL_UNPACK_LSB_FIRST, &pSave->fLsbFirst);
2270 Assert(pSave->fLsbFirst == GL_FALSE);
2271
2272 pSave->cSkipRows = 0;
2273 glGetIntegerv(GL_UNPACK_SKIP_ROWS, &pSave->cSkipRows);
2274 Assert(pSave->cSkipRows == 0);
2275
2276 pSave->cSkipPixels = 0;
2277 glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &pSave->cSkipPixels);
2278 Assert(pSave->cSkipPixels == 0);
2279
2280 pSave->cSkipImages = 0;
2281 glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &pSave->cSkipImages);
2282 Assert(pSave->cSkipImages == 0);
2283
2284 VMSVGA3D_CLEAR_GL_ERRORS();
2285#endif
2286
2287 /*
2288 * Setup unpack.
2289 *
2290 * Note! We use 1 as alignment here because we currently don't do any
2291 * aligning of line pitches anywhere.
2292 */
2293 pSave->fChanged = 0;
2294 if (pSave->iAlignment != 1)
2295 {
2296 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1), pState, pContext);
2297 pSave->fChanged |= VMSVGAPACKPARAMS_ALIGNMENT;
2298 }
2299 if (pSave->cxRow != cxRow)
2300 {
2301 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, cxRow), pState, pContext);
2302 pSave->fChanged |= VMSVGAPACKPARAMS_ROW_LENGTH;
2303 }
2304 if (pSave->cyImage != cyImage)
2305 {
2306 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, cyImage), pState, pContext);
2307 pSave->fChanged |= VMSVGAPACKPARAMS_IMAGE_HEIGHT;
2308 }
2309#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2310 if (pSave->fSwapBytes != 0)
2311 {
2312 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE), pState, pContext);
2313 pSave->fChanged |= VMSVGAPACKPARAMS_SWAP_BYTES;
2314 }
2315 if (pSave->fLsbFirst != 0)
2316 {
2317 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE), pState, pContext);
2318 pSave->fChanged |= VMSVGAPACKPARAMS_LSB_FIRST;
2319 }
2320 if (pSave->cSkipRows != 0)
2321 {
2322 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS, 0), pState, pContext);
2323 pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_ROWS;
2324 }
2325 if (pSave->cSkipPixels != 0)
2326 {
2327 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0), pState, pContext);
2328 pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_PIXELS;
2329 }
2330 if (pSave->cSkipImages != 0)
2331 {
2332 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0), pState, pContext);
2333 pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_IMAGES;
2334 }
2335#endif
2336}
2337
2338
2339/**
2340 * Restores texture unpacking parameters.
2341 *
2342 * @param pState The VMSVGA3D state structure.
2343 * @param pContext The active context.
2344 * @param pSave Where stuff was saved.
2345 */
2346void vmsvga3dOglRestoreUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext,
2347 PCVMSVGAPACKPARAMS pSave)
2348{
2349 RT_NOREF(pState);
2350
2351 if (pSave->fChanged & VMSVGAPACKPARAMS_ALIGNMENT)
2352 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, pSave->iAlignment), pState, pContext);
2353 if (pSave->fChanged & VMSVGAPACKPARAMS_ROW_LENGTH)
2354 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, pSave->cxRow), pState, pContext);
2355 if (pSave->fChanged & VMSVGAPACKPARAMS_IMAGE_HEIGHT)
2356 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, pSave->cyImage), pState, pContext);
2357#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2358 if (pSave->fChanged & VMSVGAPACKPARAMS_SWAP_BYTES)
2359 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SWAP_BYTES, pSave->fSwapBytes), pState, pContext);
2360 if (pSave->fChanged & VMSVGAPACKPARAMS_LSB_FIRST)
2361 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_LSB_FIRST, pSave->fLsbFirst), pState, pContext);
2362 if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_ROWS)
2363 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS, pSave->cSkipRows), pState, pContext);
2364 if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_PIXELS)
2365 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS, pSave->cSkipPixels), pState, pContext);
2366 if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_IMAGES)
2367 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_IMAGES, pSave->cSkipImages), pState, pContext);
2368#endif
2369}
2370
2371/**
2372 * Create D3D/OpenGL texture object for the specified surface.
2373 *
2374 * Surfaces are created when needed.
2375 *
2376 * @param pThisCC The device context.
2377 * @param pContext The context.
2378 * @param idAssociatedContext Probably the same as pContext->id.
2379 * @param pSurface The surface to create the texture for.
2380 */
2381static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext,
2382 PVMSVGA3DSURFACE pSurface)
2383{
2384 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
2385
2386 RT_NOREF(idAssociatedContext);
2387
2388 LogFunc(("sid=%u\n", pSurface->id));
2389
2390 uint32_t const numMipLevels = pSurface->cLevels;
2391
2392 /* Fugure out what kind of texture we are creating. */
2393 GLenum binding;
2394 GLenum target;
2395 if (pSurface->f.s.surface1Flags & SVGA3D_SURFACE_CUBEMAP)
2396 {
2397 Assert(pSurface->cFaces == 6);
2398
2399 binding = GL_TEXTURE_BINDING_CUBE_MAP;
2400 target = GL_TEXTURE_CUBE_MAP;
2401 }
2402 else
2403 {
2404 if (pSurface->paMipmapLevels[0].mipmapSize.depth > 1)
2405 {
2406 binding = GL_TEXTURE_BINDING_3D;
2407 target = GL_TEXTURE_3D;
2408 }
2409 else
2410 {
2411 Assert(pSurface->cFaces == 1);
2412
2413 binding = GL_TEXTURE_BINDING_2D;
2414 target = GL_TEXTURE_2D;
2415 }
2416 }
2417
2418 /* All textures are created in the SharedCtx. */
2419 uint32_t idPrevCtx = pState->idActiveContext;
2420 pContext = &pState->SharedCtx;
2421 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
2422
2423 glGenTextures(1, &pSurface->oglId.texture);
2424 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2425 if (pSurface->fEmulated)
2426 {
2427 glGenTextures(1, &pSurface->idEmulated);
2428 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2429 }
2430 pSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_TEXTURE;
2431
2432 GLint activeTexture = 0;
2433 glGetIntegerv(binding, &activeTexture);
2434 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2435
2436 /* Must bind texture to the current context in order to change it. */
2437 glBindTexture(target, pSurface->oglId.texture);
2438 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2439
2440 /* Set the unpacking parameters. */
2441 VMSVGAPACKPARAMS SavedParams;
2442 vmsvga3dOglSetUnpackParams(pState, pContext, 0, 0, &SavedParams);
2443
2444 /** @todo Set the mip map generation filter settings. */
2445
2446 /* Set the mipmap base and max level parameters. */
2447 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
2448 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2449 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, pSurface->cLevels - 1);
2450 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2451
2452 if (pSurface->fDirty)
2453 LogFunc(("sync dirty texture\n"));
2454
2455 /* Always allocate and initialize all mipmap levels; non-initialized mipmap levels used as render targets cause failures. */
2456 if (target == GL_TEXTURE_3D)
2457 {
2458 for (uint32_t i = 0; i < numMipLevels; ++i)
2459 {
2460 /* Allocate and initialize texture memory. Passing the zero filled pSurfaceData avoids
2461 * exposing random host memory to the guest and helps a with the fedora 21 surface
2462 * corruption issues (launchpad, background, search field, login).
2463 */
2464 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i];
2465
2466 LogFunc(("sync dirty 3D texture mipmap level %d (pitch %x) (dirty %d)\n",
2467 i, pMipLevel->cbSurfacePitch, pMipLevel->fDirty));
2468
2469 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2470 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2471 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2472 {
2473 pState->ext.glCompressedTexImage3D(GL_TEXTURE_3D,
2474 i,
2475 pSurface->internalFormatGL,
2476 pMipLevel->mipmapSize.width,
2477 pMipLevel->mipmapSize.height,
2478 pMipLevel->mipmapSize.depth,
2479 0,
2480 pMipLevel->cbSurface,
2481 pMipLevel->pSurfaceData);
2482 }
2483 else
2484 {
2485 pState->ext.glTexImage3D(GL_TEXTURE_3D,
2486 i,
2487 pSurface->internalFormatGL,
2488 pMipLevel->mipmapSize.width,
2489 pMipLevel->mipmapSize.height,
2490 pMipLevel->mipmapSize.depth,
2491 0, /* border */
2492 pSurface->formatGL,
2493 pSurface->typeGL,
2494 pMipLevel->pSurfaceData);
2495 }
2496 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2497
2498 pMipLevel->fDirty = false;
2499 }
2500 }
2501 else if (target == GL_TEXTURE_CUBE_MAP)
2502 {
2503 for (uint32_t iFace = 0; iFace < 6; ++iFace)
2504 {
2505 GLenum const Face = vmsvga3dCubemapFaceFromIndex(iFace);
2506
2507 for (uint32_t i = 0; i < numMipLevels; ++i)
2508 {
2509 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[iFace * numMipLevels + i];
2510 Assert(pMipLevel->mipmapSize.width == pMipLevel->mipmapSize.height);
2511 Assert(pMipLevel->mipmapSize.depth == 1);
2512
2513 LogFunc(("sync cube texture face %d mipmap level %d (dirty %d)\n",
2514 iFace, i, pMipLevel->fDirty));
2515
2516 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2517 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2518 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2519 {
2520 pState->ext.glCompressedTexImage2D(Face,
2521 i,
2522 pSurface->internalFormatGL,
2523 pMipLevel->mipmapSize.width,
2524 pMipLevel->mipmapSize.height,
2525 0,
2526 pMipLevel->cbSurface,
2527 pMipLevel->pSurfaceData);
2528 }
2529 else
2530 {
2531 glTexImage2D(Face,
2532 i,
2533 pSurface->internalFormatGL,
2534 pMipLevel->mipmapSize.width,
2535 pMipLevel->mipmapSize.height,
2536 0,
2537 pSurface->formatGL,
2538 pSurface->typeGL,
2539 pMipLevel->pSurfaceData);
2540 }
2541 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2542
2543 pMipLevel->fDirty = false;
2544 }
2545 }
2546 }
2547 else if (target == GL_TEXTURE_2D)
2548 {
2549 for (uint32_t i = 0; i < numMipLevels; ++i)
2550 {
2551 /* Allocate and initialize texture memory. Passing the zero filled pSurfaceData avoids
2552 * exposing random host memory to the guest and helps a with the fedora 21 surface
2553 * corruption issues (launchpad, background, search field, login).
2554 */
2555 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i];
2556 Assert(pMipLevel->mipmapSize.depth == 1);
2557
2558 LogFunc(("sync dirty texture mipmap level %d (pitch %x) (dirty %d)\n",
2559 i, pMipLevel->cbSurfacePitch, pMipLevel->fDirty));
2560
2561 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2562 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2563 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2564 {
2565 pState->ext.glCompressedTexImage2D(GL_TEXTURE_2D,
2566 i,
2567 pSurface->internalFormatGL,
2568 pMipLevel->mipmapSize.width,
2569 pMipLevel->mipmapSize.height,
2570 0,
2571 pMipLevel->cbSurface,
2572 pMipLevel->pSurfaceData);
2573 }
2574 else
2575 {
2576 glTexImage2D(GL_TEXTURE_2D,
2577 i,
2578 pSurface->internalFormatGL,
2579 pMipLevel->mipmapSize.width,
2580 pMipLevel->mipmapSize.height,
2581 0,
2582 pSurface->formatGL,
2583 pSurface->typeGL,
2584 NULL);
2585 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2586
2587 if (pSurface->fEmulated)
2588 {
2589 /* Bind the emulated texture and init it. */
2590 glBindTexture(GL_TEXTURE_2D, pSurface->idEmulated);
2591 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2592
2593 glTexImage2D(GL_TEXTURE_2D,
2594 i,
2595 pSurface->internalFormatGL,
2596 pMipLevel->mipmapSize.width,
2597 pMipLevel->mipmapSize.height,
2598 0,
2599 pSurface->formatGL,
2600 pSurface->typeGL,
2601 NULL);
2602 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2603 }
2604
2605 /* Fetch texture data: either to the actual or to the emulated texture.
2606 * The pSurfaceData buffer may be smaller than the entire texture
2607 * for emulated formats, in which case only part of the texture is synched.
2608 */
2609 uint32_t cBlocksX = pMipLevel->mipmapSize.width / pSurface->cxBlock;
2610 uint32_t cBlocksY = pMipLevel->mipmapSize.height / pSurface->cyBlock;
2611 glTexSubImage2D(GL_TEXTURE_2D,
2612 i,
2613 0,
2614 0,
2615 cBlocksX,
2616 cBlocksY,
2617 pSurface->formatGL,
2618 pSurface->typeGL,
2619 pMipLevel->pSurfaceData);
2620 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2621
2622 if (pSurface->fEmulated)
2623 {
2624 /* Update the actual texture using the format converter. */
2625 FormatConvUpdateTexture(pState, pContext, pSurface, i);
2626
2627 /* Rebind the actual texture. */
2628 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
2629 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2630 }
2631 }
2632 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2633
2634 pMipLevel->fDirty = false;
2635 }
2636 }
2637
2638 pSurface->fDirty = false;
2639
2640 /* Restore unpacking parameters. */
2641 vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams);
2642
2643 /* Restore the old active texture. */
2644 glBindTexture(target, activeTexture);
2645 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2646
2647 pSurface->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_TEXTURE;
2648 pSurface->targetGL = target;
2649 pSurface->bindingGL = binding;
2650
2651 if (idPrevCtx < pState->cContexts && pState->papContexts[idPrevCtx]->id == idPrevCtx)
2652 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pState->papContexts[idPrevCtx]);
2653 return VINF_SUCCESS;
2654}
2655
2656
2657/**
2658 * Backend worker for implementing SVGA_3D_CMD_SURFACE_STRETCHBLT.
2659 *
2660 * @returns VBox status code.
2661 * @param pThis The VGA device instance.
2662 * @param pState The VMSVGA3d state.
2663 * @param pDstSurface The destination host surface.
2664 * @param uDstFace The destination face (valid).
2665 * @param uDstMipmap The destination mipmap level (valid).
2666 * @param pDstBox The destination box.
2667 * @param pSrcSurface The source host surface.
2668 * @param uSrcFace The destination face (valid).
2669 * @param uSrcMipmap The source mimap level (valid).
2670 * @param pSrcBox The source box.
2671 * @param enmMode The strecht blt mode .
2672 * @param pContext The VMSVGA3d context (already current for OGL).
2673 */
2674static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBlt(PVGASTATE pThis, PVMSVGA3DSTATE pState,
2675 PVMSVGA3DSURFACE pDstSurface, uint32_t uDstFace, uint32_t uDstMipmap, SVGA3dBox const *pDstBox,
2676 PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcFace, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox,
2677 SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext)
2678{
2679 RT_NOREF(pThis);
2680
2681 AssertReturn( RT_BOOL(pSrcSurface->f.s.surface1Flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
2682 == RT_BOOL(pDstSurface->f.s.surface1Flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL), VERR_NOT_IMPLEMENTED);
2683
2684 GLenum glAttachment = GL_COLOR_ATTACHMENT0;
2685 GLbitfield glMask = GL_COLOR_BUFFER_BIT;
2686 if (pDstSurface->f.s.surface1Flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
2687 {
2688 /** @todo Need GL_DEPTH_STENCIL_ATTACHMENT for depth/stencil formats? */
2689 glAttachment = GL_DEPTH_ATTACHMENT;
2690 glMask = GL_DEPTH_BUFFER_BIT;
2691 }
2692
2693 /* Activate the read and draw framebuffer objects. */
2694 pState->ext.glBindFramebuffer(GL_READ_FRAMEBUFFER, pContext->idReadFramebuffer);
2695 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2696 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pContext->idDrawFramebuffer);
2697 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2698
2699 /* Bind the source and destination objects to the right place. */
2700 GLenum textarget;
2701 if (pSrcSurface->targetGL == GL_TEXTURE_CUBE_MAP)
2702 textarget = vmsvga3dCubemapFaceFromIndex(uSrcFace);
2703 else
2704 {
2705 /// @todo later AssertMsg(pSrcSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pSrcSurface->targetGL));
2706 textarget = GL_TEXTURE_2D;
2707 }
2708 pState->ext.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, textarget,
2709 pSrcSurface->oglId.texture, uSrcMipmap);
2710 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2711
2712 if (pDstSurface->targetGL == GL_TEXTURE_CUBE_MAP)
2713 textarget = vmsvga3dCubemapFaceFromIndex(uDstFace);
2714 else
2715 {
2716 /// @todo later AssertMsg(pDstSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pDstSurface->targetGL));
2717 textarget = GL_TEXTURE_2D;
2718 }
2719 pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, textarget,
2720 pDstSurface->oglId.texture, uDstMipmap);
2721 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2722
2723 Log(("src conv. (%d,%d)(%d,%d); dest conv (%d,%d)(%d,%d)\n",
2724 pSrcBox->x, D3D_TO_OGL_Y_COORD(pSrcSurface, pSrcBox->y + pSrcBox->h),
2725 pSrcBox->x + pSrcBox->w, D3D_TO_OGL_Y_COORD(pSrcSurface, pSrcBox->y),
2726 pDstBox->x, D3D_TO_OGL_Y_COORD(pDstSurface, pDstBox->y + pDstBox->h),
2727 pDstBox->x + pDstBox->w, D3D_TO_OGL_Y_COORD(pDstSurface, pDstBox->y)));
2728
2729 pState->ext.glBlitFramebuffer(pSrcBox->x,
2730 pSrcBox->y,
2731 pSrcBox->x + pSrcBox->w, /* exclusive. */
2732 pSrcBox->y + pSrcBox->h,
2733 pDstBox->x,
2734 pDstBox->y,
2735 pDstBox->x + pDstBox->w, /* exclusive. */
2736 pDstBox->y + pDstBox->h,
2737 glMask,
2738 (enmMode == SVGA3D_STRETCH_BLT_POINT) ? GL_NEAREST : GL_LINEAR);
2739 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2740
2741 /* Reset the frame buffer association */
2742 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, pContext->idFramebuffer);
2743 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2744
2745 return VINF_SUCCESS;
2746}
2747
2748/**
2749 * Save texture packing parameters and loads those appropriate for the given
2750 * surface.
2751 *
2752 * @param pState The VMSVGA3D state structure.
2753 * @param pContext The active context.
2754 * @param pSurface The surface.
2755 * @param pSave Where to save stuff.
2756 */
2757void vmsvga3dOglSetPackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface,
2758 PVMSVGAPACKPARAMS pSave)
2759{
2760 RT_NOREF(pState);
2761 /*
2762 * Save (ignore errors, setting the defaults we want and avoids restore).
2763 */
2764 pSave->iAlignment = 1;
2765 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_PACK_ALIGNMENT, &pSave->iAlignment), pState, pContext);
2766 pSave->cxRow = 0;
2767 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_PACK_ROW_LENGTH, &pSave->cxRow), pState, pContext);
2768
2769#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2770 pSave->cyImage = 0;
2771 glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &pSave->cyImage);
2772 Assert(pSave->cyImage == 0);
2773
2774 pSave->fSwapBytes = GL_FALSE;
2775 glGetBooleanv(GL_PACK_SWAP_BYTES, &pSave->fSwapBytes);
2776 Assert(pSave->fSwapBytes == GL_FALSE);
2777
2778 pSave->fLsbFirst = GL_FALSE;
2779 glGetBooleanv(GL_PACK_LSB_FIRST, &pSave->fLsbFirst);
2780 Assert(pSave->fLsbFirst == GL_FALSE);
2781
2782 pSave->cSkipRows = 0;
2783 glGetIntegerv(GL_PACK_SKIP_ROWS, &pSave->cSkipRows);
2784 Assert(pSave->cSkipRows == 0);
2785
2786 pSave->cSkipPixels = 0;
2787 glGetIntegerv(GL_PACK_SKIP_PIXELS, &pSave->cSkipPixels);
2788 Assert(pSave->cSkipPixels == 0);
2789
2790 pSave->cSkipImages = 0;
2791 glGetIntegerv(GL_PACK_SKIP_IMAGES, &pSave->cSkipImages);
2792 Assert(pSave->cSkipImages == 0);
2793
2794 VMSVGA3D_CLEAR_GL_ERRORS();
2795#endif
2796
2797 /*
2798 * Setup unpack.
2799 *
2800 * Note! We use 1 as alignment here because we currently don't do any
2801 * aligning of line pitches anywhere.
2802 */
2803 NOREF(pSurface);
2804 if (pSave->iAlignment != 1)
2805 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 1), pState, pContext);
2806 if (pSave->cxRow != 0)
2807 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ROW_LENGTH, 0), pState, pContext);
2808#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2809 if (pSave->cyImage != 0)
2810 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0), pState, pContext);
2811 if (pSave->fSwapBytes != 0)
2812 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE), pState, pContext);
2813 if (pSave->fLsbFirst != 0)
2814 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE), pState, pContext);
2815 if (pSave->cSkipRows != 0)
2816 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_ROWS, 0), pState, pContext);
2817 if (pSave->cSkipPixels != 0)
2818 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_PIXELS, 0), pState, pContext);
2819 if (pSave->cSkipImages != 0)
2820 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_IMAGES, 0), pState, pContext);
2821#endif
2822}
2823
2824
2825/**
2826 * Restores texture packing parameters.
2827 *
2828 * @param pState The VMSVGA3D state structure.
2829 * @param pContext The active context.
2830 * @param pSurface The surface.
2831 * @param pSave Where stuff was saved.
2832 */
2833void vmsvga3dOglRestorePackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface,
2834 PCVMSVGAPACKPARAMS pSave)
2835{
2836 RT_NOREF(pState, pSurface);
2837 if (pSave->iAlignment != 1)
2838 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, pSave->iAlignment), pState, pContext);
2839 if (pSave->cxRow != 0)
2840 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ROW_LENGTH, pSave->cxRow), pState, pContext);
2841#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2842 if (pSave->cyImage != 0)
2843 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_IMAGE_HEIGHT, pSave->cyImage), pState, pContext);
2844 if (pSave->fSwapBytes != 0)
2845 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SWAP_BYTES, pSave->fSwapBytes), pState, pContext);
2846 if (pSave->fLsbFirst != 0)
2847 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_LSB_FIRST, pSave->fLsbFirst), pState, pContext);
2848 if (pSave->cSkipRows != 0)
2849 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_ROWS, pSave->cSkipRows), pState, pContext);
2850 if (pSave->cSkipPixels != 0)
2851 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_PIXELS, pSave->cSkipPixels), pState, pContext);
2852 if (pSave->cSkipImages != 0)
2853 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_IMAGES, pSave->cSkipImages), pState, pContext);
2854#endif
2855}
2856
2857
2858/**
2859 * Backend worker for implementing SVGA_3D_CMD_SURFACE_DMA that copies one box.
2860 *
2861 * @returns Failure status code or @a rc.
2862 * @param pThis The shared VGA/VMSVGA instance data.
2863 * @param pThisCC The VGA/VMSVGA state for ring-3.
2864 * @param pState The VMSVGA3d state.
2865 * @param pSurface The host surface.
2866 * @param pMipLevel Mipmap level. The caller knows it already.
2867 * @param uHostFace The host face (valid).
2868 * @param uHostMipmap The host mipmap level (valid).
2869 * @param GuestPtr The guest pointer.
2870 * @param cbGuestPitch The guest pitch.
2871 * @param transfer The transfer direction.
2872 * @param pBox The box to copy (clipped, valid, except for guest's srcx, srcy, srcz).
2873 * @param pContext The context (for OpenGL).
2874 * @param rc The current rc for all boxes.
2875 * @param iBox The current box number (for Direct 3D).
2876 */
2877static DECLCALLBACK(int) vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface,
2878 PVMSVGA3DMIPMAPLEVEL pMipLevel, uint32_t uHostFace, uint32_t uHostMipmap,
2879 SVGAGuestPtr GuestPtr, uint32_t cbGuestPitch, SVGA3dTransferType transfer,
2880 SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox)
2881{
2882 RT_NOREF(iBox);
2883
2884 switch (pSurface->enmOGLResType)
2885 {
2886 case VMSVGA3D_OGLRESTYPE_TEXTURE:
2887 {
2888 uint32_t cbSurfacePitch;
2889 uint8_t *pDoubleBuffer;
2890 uint64_t offHst;
2891
2892 uint32_t const u32HostBlockX = pBox->x / pSurface->cxBlock;
2893 uint32_t const u32HostBlockY = pBox->y / pSurface->cyBlock;
2894 uint32_t const u32HostZ = pBox->z;
2895 Assert(u32HostBlockX * pSurface->cxBlock == pBox->x);
2896 Assert(u32HostBlockY * pSurface->cyBlock == pBox->y);
2897
2898 uint32_t const u32GuestBlockX = pBox->srcx / pSurface->cxBlock;
2899 uint32_t const u32GuestBlockY = pBox->srcy / pSurface->cyBlock;
2900 uint32_t const u32GuestZ = pBox->srcz / pSurface->cyBlock;
2901 Assert(u32GuestBlockX * pSurface->cxBlock == pBox->srcx);
2902 Assert(u32GuestBlockY * pSurface->cyBlock == pBox->srcy);
2903
2904 uint32_t const cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock;
2905 uint32_t const cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock;
2906 AssertMsgReturn(cBlocksX && cBlocksY, ("Empty box %dx%d\n", pBox->w, pBox->h), VERR_INTERNAL_ERROR);
2907
2908 GLenum texImageTarget;
2909 if (pSurface->targetGL == GL_TEXTURE_3D)
2910 {
2911 texImageTarget = GL_TEXTURE_3D;
2912 }
2913 else if (pSurface->targetGL == GL_TEXTURE_CUBE_MAP)
2914 {
2915 texImageTarget = vmsvga3dCubemapFaceFromIndex(uHostFace);
2916 }
2917 else
2918 {
2919 AssertMsg(pSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pSurface->targetGL));
2920 texImageTarget = GL_TEXTURE_2D;
2921 }
2922
2923 /* The buffer must be large enough to hold entire texture in the OpenGL format. */
2924 pDoubleBuffer = (uint8_t *)RTMemAlloc(pSurface->cbBlockGL * pMipLevel->cBlocks);
2925 AssertReturn(pDoubleBuffer, VERR_NO_MEMORY);
2926
2927 if (transfer == SVGA3D_READ_HOST_VRAM)
2928 {
2929 /* Read the entire texture to the double buffer. */
2930 GLint activeTexture;
2931
2932 /* Must bind texture to the current context in order to read it. */
2933 glGetIntegerv(pSurface->bindingGL, &activeTexture);
2934 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2935
2936 glBindTexture(pSurface->targetGL, GLTextureId(pSurface));
2937 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2938
2939 if (pSurface->fEmulated)
2940 {
2941 FormatConvReadTexture(pState, pContext, pSurface, uHostMipmap);
2942 }
2943
2944 /* Set row length and alignment of the input data. */
2945 VMSVGAPACKPARAMS SavedParams;
2946 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
2947
2948 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2949 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2950 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2951 {
2952 pState->ext.glGetCompressedTexImage(texImageTarget, uHostMipmap, pDoubleBuffer);
2953 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2954 }
2955 else
2956 {
2957 glGetTexImage(texImageTarget, uHostMipmap, pSurface->formatGL, pSurface->typeGL, pDoubleBuffer);
2958 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2959 }
2960
2961 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
2962
2963 /* Restore the old active texture. */
2964 glBindTexture(pSurface->targetGL, activeTexture);
2965 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2966
2967 offHst = u32HostBlockX * pSurface->cbBlock + u32HostBlockY * pMipLevel->cbSurfacePitch + u32HostZ * pMipLevel->cbSurfacePlane;
2968 cbSurfacePitch = pMipLevel->cbSurfacePitch;
2969 }
2970 else
2971 {
2972 /* The buffer will contain only the copied rectangle. */
2973 offHst = 0;
2974 cbSurfacePitch = cBlocksX * pSurface->cbBlock;
2975 }
2976
2977 uint64_t offGst = u32GuestBlockX * pSurface->cbBlock + u32GuestBlockY * cbGuestPitch + u32GuestZ * cbGuestPitch * pMipLevel->mipmapSize.height;
2978
2979 for (uint32_t iPlane = 0; iPlane < pBox->d; ++iPlane)
2980 {
2981 AssertBreak(offHst < UINT32_MAX);
2982 AssertBreak(offGst < UINT32_MAX);
2983
2984 rc = vmsvgaR3GmrTransfer(pThis,
2985 pThisCC,
2986 transfer,
2987 pDoubleBuffer,
2988 pMipLevel->cbSurface,
2989 (uint32_t)offHst,
2990 cbSurfacePitch,
2991 GuestPtr,
2992 (uint32_t)offGst,
2993 cbGuestPitch,
2994 cBlocksX * pSurface->cbBlock,
2995 cBlocksY);
2996 AssertRC(rc);
2997
2998 offHst += pMipLevel->cbSurfacePlane;
2999 offGst += pMipLevel->mipmapSize.height * cbGuestPitch;
3000 }
3001
3002 /* Update the opengl surface data. */
3003 if (transfer == SVGA3D_WRITE_HOST_VRAM)
3004 {
3005 GLint activeTexture = 0;
3006 glGetIntegerv(pSurface->bindingGL, &activeTexture);
3007 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3008
3009 /* Must bind texture to the current context in order to change it. */
3010 glBindTexture(pSurface->targetGL, GLTextureId(pSurface));
3011 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3012
3013 LogFunc(("copy texture mipmap level %d (pitch %x)\n", uHostMipmap, pMipLevel->cbSurfacePitch));
3014
3015 /* Set row length and alignment of the input data. */
3016 /* We do not need to set ROW_LENGTH to w here, because the image in pDoubleBuffer is tightly packed. */
3017 VMSVGAPACKPARAMS SavedParams;
3018 vmsvga3dOglSetUnpackParams(pState, pContext, 0, 0, &SavedParams);
3019
3020 if (texImageTarget == GL_TEXTURE_3D)
3021 {
3022 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
3023 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
3024 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
3025 {
3026 pState->ext.glCompressedTexSubImage3D(texImageTarget,
3027 uHostMipmap,
3028 pBox->x,
3029 pBox->y,
3030 pBox->z,
3031 pBox->w,
3032 pBox->h,
3033 pBox->d,
3034 pSurface->internalFormatGL,
3035 cbSurfacePitch * cBlocksY * pBox->d,
3036 pDoubleBuffer);
3037 }
3038 else
3039 {
3040 pState->ext.glTexSubImage3D(texImageTarget,
3041 uHostMipmap,
3042 u32HostBlockX,
3043 u32HostBlockY,
3044 pBox->z,
3045 cBlocksX,
3046 cBlocksY,
3047 pBox->d,
3048 pSurface->formatGL,
3049 pSurface->typeGL,
3050 pDoubleBuffer);
3051 }
3052 }
3053 else
3054 {
3055 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
3056 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
3057 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
3058 {
3059 pState->ext.glCompressedTexSubImage2D(texImageTarget,
3060 uHostMipmap,
3061 pBox->x,
3062 pBox->y,
3063 pBox->w,
3064 pBox->h,
3065 pSurface->internalFormatGL,
3066 cbSurfacePitch * cBlocksY,
3067 pDoubleBuffer);
3068 }
3069 else
3070 {
3071 glTexSubImage2D(texImageTarget,
3072 uHostMipmap,
3073 u32HostBlockX,
3074 u32HostBlockY,
3075 cBlocksX,
3076 cBlocksY,
3077 pSurface->formatGL,
3078 pSurface->typeGL,
3079 pDoubleBuffer);
3080 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3081
3082 if (pSurface->fEmulated)
3083 {
3084 /* Convert the texture to the actual texture if necessary */
3085 FormatConvUpdateTexture(pState, pContext, pSurface, uHostMipmap);
3086 }
3087 }
3088 }
3089 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3090
3091 /* Restore old values. */
3092 vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams);
3093
3094 /* Restore the old active texture. */
3095 glBindTexture(pSurface->targetGL, activeTexture);
3096 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3097 }
3098
3099 Log4(("first line:\n%.*Rhxd\n", cBlocksX * pSurface->cbBlock, pDoubleBuffer));
3100
3101 /* Free the double buffer. */
3102 RTMemFree(pDoubleBuffer);
3103 break;
3104 }
3105
3106 case VMSVGA3D_OGLRESTYPE_BUFFER:
3107 {
3108 /* Buffers are uncompressed. */
3109 AssertReturn(pSurface->cxBlock == 1 && pSurface->cyBlock == 1, VERR_INTERNAL_ERROR);
3110
3111 /* Caller already clipped pBox and buffers are 1-dimensional. */
3112 Assert(pBox->y == 0 && pBox->h == 1 && pBox->z == 0 && pBox->d == 1);
3113
3114 VMSVGA3D_CLEAR_GL_ERRORS();
3115 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
3116 if (VMSVGA3D_GL_IS_SUCCESS(pContext))
3117 {
3118 GLenum enmGlTransfer = (transfer == SVGA3D_READ_HOST_VRAM) ? GL_READ_ONLY : GL_WRITE_ONLY;
3119 uint8_t *pbData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, enmGlTransfer);
3120 if (RT_LIKELY(pbData != NULL))
3121 {
3122#if defined(VBOX_STRICT) && defined(RT_OS_DARWIN)
3123 GLint cbStrictBufSize;
3124 glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &cbStrictBufSize);
3125 Assert(VMSVGA3D_GL_IS_SUCCESS(pContext));
3126 AssertMsg(cbStrictBufSize >= (int32_t)pMipLevel->cbSurface,
3127 ("cbStrictBufSize=%#x cbSurface=%#x pContext->id=%#x\n", (uint32_t)cbStrictBufSize, pMipLevel->cbSurface, pContext->id));
3128#endif
3129 Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n",
3130 (pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_VERTEXBUFFER ? "vertex" :
3131 (pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_INDEXBUFFER ? "index" : "buffer",
3132 pBox->x, pBox->y, pBox->x + pBox->w, pBox->y + pBox->h));
3133
3134 /* The caller already copied the data to the pMipLevel->pSurfaceData buffer, see VMSVGA3DSURFACE_NEEDS_DATA. */
3135 uint32_t const offHst = pBox->x * pSurface->cbBlock;
3136 uint32_t const cbWidth = pBox->w * pSurface->cbBlock;
3137
3138 memcpy(pbData + offHst, (uint8_t *)pMipLevel->pSurfaceData + offHst, cbWidth);
3139
3140 Log4(("Buffer updated at [0x%x;0x%x):\n%.*Rhxd\n", offHst, offHst + cbWidth, cbWidth, (uint8_t *)pbData + offHst));
3141
3142 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
3143 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3144 }
3145 else
3146 VMSVGA3D_GL_GET_AND_COMPLAIN(pState, pContext, ("glMapBuffer(GL_ARRAY_BUFFER, %#x) -> NULL\n", enmGlTransfer));
3147 }
3148 else
3149 VMSVGA3D_GL_COMPLAIN(pState, pContext, ("glBindBuffer(GL_ARRAY_BUFFER, %#x)\n", pSurface->oglId.buffer));
3150 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
3151 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3152 break;
3153 }
3154
3155 default:
3156 AssertFailed();
3157 break;
3158 }
3159
3160 return rc;
3161}
3162
3163static DECLCALLBACK(int) vmsvga3dBackGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter)
3164{
3165 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3166 PVMSVGA3DSURFACE pSurface;
3167 int rc = VINF_SUCCESS;
3168 PVMSVGA3DCONTEXT pContext;
3169 uint32_t cid;
3170 GLint activeTexture = 0;
3171
3172 AssertReturn(pState, VERR_NO_MEMORY);
3173
3174 rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
3175 AssertRCReturn(rc, rc);
3176
3177 Assert(filter != SVGA3D_TEX_FILTER_FLATCUBIC);
3178 Assert(filter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
3179 pSurface->autogenFilter = filter;
3180
3181 LogFunc(("sid=%u filter=%d\n", sid, filter));
3182
3183 cid = SVGA3D_INVALID_ID;
3184 pContext = &pState->SharedCtx;
3185 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
3186
3187 if (pSurface->oglId.texture == OPENGL_INVALID_ID)
3188 {
3189 /* Unknown surface type; turn it into a texture. */
3190 LogFunc(("unknown src surface id=%x type=%d format=%d -> create texture\n", sid, pSurface->f.s.surface1Flags, pSurface->format));
3191 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface);
3192 AssertRCReturn(rc, rc);
3193 }
3194 else
3195 {
3196 /** @todo new filter */
3197 AssertFailed();
3198 }
3199
3200 glGetIntegerv(pSurface->bindingGL, &activeTexture);
3201 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3202
3203 /* Must bind texture to the current context in order to change it. */
3204 glBindTexture(pSurface->targetGL, pSurface->oglId.texture);
3205 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3206
3207 /* Generate the mip maps. */
3208 pState->ext.glGenerateMipmap(pSurface->targetGL);
3209 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3210
3211 /* Restore the old texture. */
3212 glBindTexture(pSurface->targetGL, activeTexture);
3213 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3214
3215 return VINF_SUCCESS;
3216}
3217
3218
3219#ifdef RT_OS_LINUX
3220/**
3221 * X11 event handling thread.
3222 *
3223 * @returns VINF_SUCCESS (ignored)
3224 * @param hThreadSelf thread handle
3225 * @param pvUser pointer to pState structure
3226 */
3227static DECLCALLBACK(int) vmsvga3dXEventThread(RTTHREAD hThreadSelf, void *pvUser)
3228{
3229 RT_NOREF(hThreadSelf);
3230 PVMSVGA3DSTATE pState = (PVMSVGA3DSTATE)pvUser;
3231 while (!pState->bTerminate)
3232 {
3233 while (XPending(pState->display) > 0)
3234 {
3235 XEvent event;
3236 XNextEvent(pState->display, &event);
3237
3238 switch (event.type)
3239 {
3240 default:
3241 break;
3242 }
3243 }
3244 /* sleep for 16ms to not burn too many cycles */
3245 RTThreadSleep(16);
3246 }
3247 return VINF_SUCCESS;
3248}
3249#endif // RT_OS_LINUX
3250
3251
3252/**
3253 * Create a new 3d context
3254 *
3255 * @returns VBox status code.
3256 * @param pThisCC The VGA/VMSVGA state for ring-3.
3257 * @param cid Context id
3258 * @param fFlags VMSVGA3D_DEF_CTX_F_XXX.
3259 */
3260int vmsvga3dContextDefineOgl(PVGASTATECC pThisCC, uint32_t cid, uint32_t fFlags)
3261{
3262 int rc;
3263 PVMSVGA3DCONTEXT pContext;
3264 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3265
3266 AssertReturn(pState, VERR_NO_MEMORY);
3267 AssertReturn( cid < SVGA3D_MAX_CONTEXT_IDS
3268 || (cid == VMSVGA3D_SHARED_CTX_ID && (fFlags & VMSVGA3D_DEF_CTX_F_SHARED_CTX)), VERR_INVALID_PARAMETER);
3269#if !defined(VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE) || !(defined(RT_OS_DARWIN))
3270 AssertReturn(!(fFlags & VMSVGA3D_DEF_CTX_F_OTHER_PROFILE), VERR_INTERNAL_ERROR_3);
3271#endif
3272
3273 Log(("vmsvga3dContextDefine id %x\n", cid));
3274
3275 if (cid == VMSVGA3D_SHARED_CTX_ID)
3276 pContext = &pState->SharedCtx;
3277 else
3278 {
3279 if (cid >= pState->cContexts)
3280 {
3281 /* Grow the array. */
3282 uint32_t cNew = RT_ALIGN(cid + 15, 16);
3283 void *pvNew = RTMemRealloc(pState->papContexts, sizeof(pState->papContexts[0]) * cNew);
3284 AssertReturn(pvNew, VERR_NO_MEMORY);
3285 pState->papContexts = (PVMSVGA3DCONTEXT *)pvNew;
3286 while (pState->cContexts < cNew)
3287 {
3288 pContext = (PVMSVGA3DCONTEXT)RTMemAllocZ(sizeof(*pContext));
3289 AssertReturn(pContext, VERR_NO_MEMORY);
3290 pContext->id = SVGA3D_INVALID_ID;
3291 pState->papContexts[pState->cContexts++] = pContext;
3292 }
3293 }
3294 /* If one already exists with this id, then destroy it now. */
3295 if (pState->papContexts[cid]->id != SVGA3D_INVALID_ID)
3296 vmsvga3dBackContextDestroy(pThisCC, cid);
3297
3298 pContext = pState->papContexts[cid];
3299 }
3300
3301 /*
3302 * Find or create the shared context if needed (necessary for sharing e.g. textures between contexts).
3303 */
3304 PVMSVGA3DCONTEXT pSharedCtx = NULL;
3305 if (!(fFlags & (VMSVGA3D_DEF_CTX_F_INIT | VMSVGA3D_DEF_CTX_F_SHARED_CTX)))
3306 {
3307 pSharedCtx = &pState->SharedCtx;
3308 if (pSharedCtx->id != VMSVGA3D_SHARED_CTX_ID)
3309 {
3310 rc = vmsvga3dContextDefineOgl(pThisCC, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX);
3311 AssertLogRelRCReturn(rc, rc);
3312
3313 /* Create resources which use the shared context. */
3314 vmsvga3dOnSharedContextDefine(pState);
3315 }
3316 }
3317
3318 /*
3319 * Initialize the context.
3320 */
3321 memset(pContext, 0, sizeof(*pContext));
3322 pContext->id = cid;
3323 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); i++)
3324 pContext->aSidActiveTextures[i] = SVGA3D_INVALID_ID;
3325
3326 pContext->state.shidVertex = SVGA3D_INVALID_ID;
3327 pContext->state.shidPixel = SVGA3D_INVALID_ID;
3328 pContext->idFramebuffer = OPENGL_INVALID_ID;
3329 pContext->idReadFramebuffer = OPENGL_INVALID_ID;
3330 pContext->idDrawFramebuffer = OPENGL_INVALID_ID;
3331
3332 rc = ShaderContextCreate(&pContext->pShaderContext);
3333 AssertRCReturn(rc, rc);
3334
3335 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); i++)
3336 pContext->state.aRenderTargets[i] = SVGA3D_INVALID_ID;
3337
3338#ifdef RT_OS_WINDOWS
3339 /* Create a context window with minimal 4x4 size. We will never use the swapchain
3340 * to present the rendered image. Rendered images from the guest will be copied to
3341 * the VMSVGA SCREEN object, which can be either an offscreen render target or
3342 * system memory in the guest VRAM.
3343 */
3344 rc = vmsvga3dContextWindowCreate(pState->hInstance, pState->pWindowThread, pState->WndRequestSem, &pContext->hwnd);
3345 AssertRCReturn(rc, rc);
3346
3347 pContext->hdc = GetDC(pContext->hwnd);
3348 AssertMsgReturn(pContext->hdc, ("GetDC %x failed with %d\n", pContext->hwnd, GetLastError()), VERR_INTERNAL_ERROR);
3349
3350 PIXELFORMATDESCRIPTOR pfd = {
3351 sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
3352 1, /* version number */
3353 PFD_DRAW_TO_WINDOW | /* support window */
3354 PFD_SUPPORT_OPENGL, /* support OpenGL */
3355 PFD_TYPE_RGBA, /* RGBA type */
3356 24, /* 24-bit color depth */
3357 0, 0, 0, 0, 0, 0, /* color bits ignored */
3358 8, /* alpha buffer */
3359 0, /* shift bit ignored */
3360 0, /* no accumulation buffer */
3361 0, 0, 0, 0, /* accum bits ignored */
3362 16, /* set depth buffer */
3363 16, /* set stencil buffer */
3364 0, /* no auxiliary buffer */
3365 PFD_MAIN_PLANE, /* main layer */
3366 0, /* reserved */
3367 0, 0, 0 /* layer masks ignored */
3368 };
3369 int pixelFormat;
3370 BOOL ret;
3371
3372 pixelFormat = ChoosePixelFormat(pContext->hdc, &pfd);
3373 /** @todo is this really necessary?? */
3374 pixelFormat = ChoosePixelFormat(pContext->hdc, &pfd);
3375 AssertMsgReturn(pixelFormat != 0, ("ChoosePixelFormat failed with %d\n", GetLastError()), VERR_INTERNAL_ERROR);
3376
3377 ret = SetPixelFormat(pContext->hdc, pixelFormat, &pfd);
3378 AssertMsgReturn(ret == TRUE, ("SetPixelFormat failed with %d\n", GetLastError()), VERR_INTERNAL_ERROR);
3379
3380 pContext->hglrc = wglCreateContext(pContext->hdc);
3381 AssertMsgReturn(pContext->hglrc, ("wglCreateContext %x failed with %d\n", pContext->hdc, GetLastError()), VERR_INTERNAL_ERROR);
3382
3383 if (pSharedCtx)
3384 {
3385 ret = wglShareLists(pSharedCtx->hglrc, pContext->hglrc);
3386 AssertMsg(ret == TRUE, ("wglShareLists(%p, %p) failed with %d\n", pSharedCtx->hglrc, pContext->hglrc, GetLastError()));
3387 }
3388
3389#elif defined(RT_OS_DARWIN)
3390 pContext->fOtherProfile = RT_BOOL(fFlags & VMSVGA3D_DEF_CTX_F_OTHER_PROFILE);
3391
3392 NativeNSOpenGLContextRef pShareContext = pSharedCtx ? pSharedCtx->cocoaContext : NULL;
3393 vmsvga3dCocoaCreateViewAndContext(&pContext->cocoaView, &pContext->cocoaContext,
3394 NULL,
3395 4, 4,
3396 pShareContext, pContext->fOtherProfile);
3397
3398#else
3399 if (pState->display == NULL)
3400 {
3401 /* get an X display and make sure we have glX 1.3 */
3402 pState->display = XOpenDisplay(0);
3403 AssertLogRelMsgReturn(pState->display, ("XOpenDisplay failed"), VERR_INTERNAL_ERROR);
3404 int glxMajor, glxMinor;
3405 Bool ret = glXQueryVersion(pState->display, &glxMajor, &glxMinor);
3406 AssertLogRelMsgReturn(ret && glxMajor == 1 && glxMinor >= 3, ("glX >=1.3 not present"), VERR_INTERNAL_ERROR);
3407 /* start our X event handling thread */
3408 rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dXEventThread, pState, 0, RTTHREADTYPE_GUI, RTTHREADFLAGS_WAITABLE, "VMSVGA3DXEVENT");
3409 AssertLogRelMsgReturn(RT_SUCCESS(rc), ("Async IO Thread creation for 3d window handling failed rc=%Rrc\n", rc), rc);
3410 }
3411
3412 Window defaultRootWindow = XDefaultRootWindow(pState->display);
3413 /* Create a small 4x4 window required for GL context. */
3414 int attrib[] =
3415 {
3416 GLX_RGBA,
3417 GLX_RED_SIZE, 1,
3418 GLX_GREEN_SIZE, 1,
3419 GLX_BLUE_SIZE, 1,
3420 //GLX_ALPHA_SIZE, 1, this flips the bbos screen
3421 GLX_DOUBLEBUFFER,
3422 None
3423 };
3424 XVisualInfo *vi = glXChooseVisual(pState->display, DefaultScreen(pState->display), attrib);
3425 AssertLogRelMsgReturn(vi, ("glXChooseVisual failed"), VERR_INTERNAL_ERROR);
3426 XSetWindowAttributes swa;
3427 swa.colormap = XCreateColormap(pState->display, defaultRootWindow, vi->visual, AllocNone);
3428 AssertLogRelMsgReturn(swa.colormap, ("XCreateColormap failed"), VERR_INTERNAL_ERROR);
3429 swa.border_pixel = 0;
3430 swa.background_pixel = 0;
3431 swa.event_mask = StructureNotifyMask;
3432 unsigned long flags = CWBorderPixel | CWBackPixel | CWColormap | CWEventMask;
3433 pContext->window = XCreateWindow(pState->display, defaultRootWindow,
3434 0, 0, 4, 4,
3435 0, vi->depth, InputOutput,
3436 vi->visual, flags, &swa);
3437 AssertLogRelMsgReturn(pContext->window, ("XCreateWindow failed"), VERR_INTERNAL_ERROR);
3438
3439 /* The window is hidden by default and never mapped, because we only render offscreen and never present to it. */
3440
3441 GLXContext shareContext = pSharedCtx ? pSharedCtx->glxContext : NULL;
3442 pContext->glxContext = glXCreateContext(pState->display, vi, shareContext, GL_TRUE);
3443 XFree(vi);
3444 AssertLogRelMsgReturn(pContext->glxContext, ("glXCreateContext failed"), VERR_INTERNAL_ERROR);
3445#endif
3446
3447 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
3448
3449 /* NULL during the first PowerOn call. */
3450 if (pState->ext.glGenFramebuffers)
3451 {
3452 /* Create a framebuffer object for this context. */
3453 pState->ext.glGenFramebuffers(1, &pContext->idFramebuffer);
3454 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3455
3456 /* Bind the object to the framebuffer target. */
3457 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, pContext->idFramebuffer);
3458 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3459
3460 /* Create read and draw framebuffer objects for this context. */
3461 pState->ext.glGenFramebuffers(1, &pContext->idReadFramebuffer);
3462 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3463
3464 pState->ext.glGenFramebuffers(1, &pContext->idDrawFramebuffer);
3465 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3466
3467 }
3468#if 0
3469 /** @todo move to shader lib!!! */
3470 /* Clear the screen */
3471 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
3472
3473 glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
3474 glClearIndex(0);
3475 glClearDepth(1);
3476 glClearStencil(0xffff);
3477 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
3478 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3479 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
3480 if (pState->ext.glProvokingVertex)
3481 pState->ext.glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
3482 /** @todo move to shader lib!!! */
3483#endif
3484 return VINF_SUCCESS;
3485}
3486
3487#if defined(RT_OS_LINUX)
3488/*
3489 * HW accelerated graphics output.
3490 */
3491
3492/**
3493 * VMSVGA3d screen data.
3494 *
3495 * Allocated on the heap and pointed to by VMSVGASCREENOBJECT::pHwScreen.
3496 */
3497typedef struct VMSVGAHWSCREEN
3498{
3499 /* OpenGL context, which is used for the screen updates. */
3500 GLXContext glxctx;
3501
3502 /* The overlay window. */
3503 Window xwindow;
3504
3505 /* The RGBA texture which hold the screen content. */
3506 GLuint idScreenTexture;
3507
3508 /* Read and draw framebuffer objects for copying a surface to the screen texture. */
3509 GLuint idReadFramebuffer;
3510 GLuint idDrawFramebuffer;
3511} VMSVGAHWSCREEN;
3512
3513/* Send a notification to the UI. */
3514#if 0 /* Unused */
3515static int vmsvga3dDrvNotifyHwScreen(PVGASTATECC pThisCC, VBOX3D_NOTIFY_TYPE enmNotification,
3516 uint32_t idScreen, Pixmap pixmap, void *pvData, size_t cbData)
3517{
3518 uint8_t au8Buffer[128];
3519 AssertLogRelMsgReturn(cbData <= sizeof(au8Buffer) - sizeof(VBOX3DNOTIFY),
3520 ("cbData %zu", cbData),
3521 VERR_INVALID_PARAMETER);
3522
3523 VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0];
3524 p->enmNotification = enmNotification;
3525 p->iDisplay = idScreen;
3526 p->u32Reserved = 0;
3527 p->cbData = cbData + sizeof(uint64_t);
3528 /* au8Data consists of a 64 bit pixmap handle followed by notification specific data. */
3529 AssertCompile(sizeof(pixmap) <= sizeof(uint64_t));
3530 *(uint64_t *)&p->au8Data[0] = (uint64_t)pixmap;
3531 memcpy(&p->au8Data[sizeof(uint64_t)], pvData, cbData);
3532
3533 int rc = pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p);
3534 return rc;
3535}
3536#endif /* Unused */
3537
3538static void vmsvga3dDrvNotifyHwOverlay(PVGASTATECC pThisCC, VBOX3D_NOTIFY_TYPE enmNotification, uint32_t idScreen)
3539{
3540 uint8_t au8Buffer[128];
3541 VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0];
3542 p->enmNotification = enmNotification;
3543 p->iDisplay = idScreen;
3544 p->u32Reserved = 0;
3545 p->cbData = sizeof(uint64_t);
3546 *(uint64_t *)&p->au8Data[0] = 0;
3547
3548 pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p);
3549}
3550
3551/* Get X Window handle of the UI Framebuffer window. */
3552static int vmsvga3dDrvQueryWindow(PVGASTATECC pThisCC, uint32_t idScreen, Window *pWindow)
3553{
3554 uint8_t au8Buffer[128];
3555 VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0];
3556 p->enmNotification = VBOX3D_NOTIFY_TYPE_HW_OVERLAY_GET_ID;
3557 p->iDisplay = idScreen;
3558 p->u32Reserved = 0;
3559 p->cbData = sizeof(uint64_t);
3560 *(uint64_t *)&p->au8Data[0] = 0;
3561
3562 int rc = pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p);
3563 if (RT_SUCCESS(rc))
3564 {
3565 *pWindow = (Window)*(uint64_t *)&p->au8Data[0];
3566 }
3567 return rc;
3568}
3569
3570static int ctxErrorHandler(Display *dpy, XErrorEvent *ev)
3571{
3572 RT_NOREF(dpy);
3573 LogRel4(("VMSVGA: XError %d\n", (int)ev->error_code));
3574 return 0;
3575}
3576
3577/* Create an overlay X window for the HW accelerated screen. */
3578static int vmsvga3dHwScreenCreate(PVMSVGA3DSTATE pState, Window parentWindow, unsigned int cWidth, unsigned int cHeight, VMSVGAHWSCREEN *p)
3579{
3580 int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
3581
3582 int rc = VINF_SUCCESS;
3583
3584 XWindowAttributes parentAttr;
3585 if (XGetWindowAttributes(pState->display, parentWindow, &parentAttr) == 0)
3586 return VERR_INVALID_PARAMETER;
3587
3588 int const idxParentScreen = XScreenNumberOfScreen(parentAttr.screen);
3589
3590 /*
3591 * Create a new GL context, which will be used for copying to the screen.
3592 */
3593
3594 /* FBConfig attributes for the overlay window. */
3595 static int const aConfigAttribList[] =
3596 {
3597 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, // Must support GLX windows
3598 GLX_DOUBLEBUFFER, False, // Double buffering had a much lower performance.
3599 GLX_RED_SIZE, 8, // True color RGB with 8 bits per channel.
3600 GLX_GREEN_SIZE, 8,
3601 GLX_BLUE_SIZE, 8,
3602 GLX_ALPHA_SIZE, 8,
3603 GLX_STENCIL_SIZE, 0, // No stencil buffer
3604 GLX_DEPTH_SIZE, 0, // No depth buffer
3605 None
3606 };
3607
3608 /* Find a suitable FB config. */
3609 int cConfigs = 0;
3610 GLXFBConfig *paConfigs = glXChooseFBConfig(pState->display, idxParentScreen, aConfigAttribList, &cConfigs);
3611 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: paConfigs %p cConfigs %d\n", (void *)paConfigs, cConfigs));
3612 if (paConfigs)
3613 {
3614 XVisualInfo *vi = NULL;
3615 int i = 0;
3616 for (; i < cConfigs; ++i)
3617 {
3618 /* Use XFree to free the data returned in the previous iteration of this loop. */
3619 if (vi)
3620 XFree(vi);
3621
3622 vi = glXGetVisualFromFBConfig(pState->display, paConfigs[i]);
3623 if (!vi)
3624 continue;
3625
3626 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: %p vid %lu screen %d depth %d r %lu g %lu b %lu clrmap %d bitsperrgb %d\n",
3627 (void *)vi->visual, vi->visualid, vi->screen, vi->depth,
3628 vi->red_mask, vi->green_mask, vi->blue_mask, vi->colormap_size, vi->bits_per_rgb));
3629
3630 /* Same screen as the parent window. */
3631 if (vi->screen != idxParentScreen)
3632 continue;
3633
3634 /* Search for 32 bits per pixel. */
3635 if (vi->depth != 32)
3636 continue;
3637
3638 /* 8 bits per color component is enough. */
3639 if (vi->bits_per_rgb != 8)
3640 continue;
3641
3642 /* Render to pixmap. */
3643 int value = 0;
3644 glXGetFBConfigAttrib(pState->display, paConfigs[i], GLX_DRAWABLE_TYPE, &value);
3645 if (!(value & GLX_WINDOW_BIT))
3646 continue;
3647
3648 /* This FB config can be used. */
3649 break;
3650 }
3651
3652 if (i < cConfigs)
3653 {
3654 /* Found a suitable config with index i. */
3655
3656 /* Create an overlay window. */
3657 XSetWindowAttributes swa;
3658 RT_ZERO(swa);
3659
3660 swa.colormap = XCreateColormap(pState->display, parentWindow, vi->visual, AllocNone);
3661 AssertLogRelMsg(swa.colormap, ("XCreateColormap failed"));
3662 swa.border_pixel = 0;
3663 swa.background_pixel = 0;
3664 swa.event_mask = StructureNotifyMask;
3665 swa.override_redirect = 1;
3666 unsigned long const swaAttrs = CWBorderPixel | CWBackPixel | CWColormap | CWEventMask | CWOverrideRedirect;
3667 p->xwindow = XCreateWindow(pState->display, parentWindow,
3668 0, 0, cWidth, cHeight, 0, vi->depth, InputOutput,
3669 vi->visual, swaAttrs, &swa);
3670 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: p->xwindow %ld\n", p->xwindow));
3671 if (p->xwindow)
3672 {
3673
3674 p->glxctx = glXCreateContext(pState->display, vi, pState->SharedCtx.glxContext, GL_TRUE);
3675 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: p->glxctx %p\n", (void *)p->glxctx));
3676 if (p->glxctx)
3677 {
3678 XMapWindow(pState->display, p->xwindow);
3679 }
3680 else
3681 {
3682 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: glXCreateContext failed\n"));
3683 rc = VERR_NOT_SUPPORTED;
3684 }
3685 }
3686 else
3687 {
3688 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: XCreateWindow failed\n"));
3689 rc = VERR_NOT_SUPPORTED;
3690 }
3691
3692 XSync(pState->display, False);
3693 }
3694 else
3695 {
3696 /* A suitable config is not found. */
3697 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: no FBConfig\n"));
3698 rc = VERR_NOT_SUPPORTED;
3699 }
3700
3701 if (vi)
3702 XFree(vi);
3703
3704 /* "Use XFree to free the memory returned by glXChooseFBConfig." */
3705 XFree(paConfigs);
3706 }
3707 else
3708 {
3709 /* glXChooseFBConfig failed. */
3710 rc = VERR_NOT_SUPPORTED;
3711 }
3712
3713 XSetErrorHandler(oldHandler);
3714 return rc;
3715}
3716
3717/* Destroy a HW accelerated screen. */
3718static void vmsvga3dHwScreenDestroy(PVMSVGA3DSTATE pState, VMSVGAHWSCREEN *p)
3719{
3720 if (p)
3721 {
3722 LogRel4(("VMSVGA: vmsvga3dHwScreenDestroy: p->xwindow %ld, ctx %p\n", p->xwindow, (void *)p->glxctx));
3723 if (p->glxctx)
3724 {
3725 /* GLX context is changed here, so other code has to set the appropriate context again. */
3726 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
3727
3728 glXMakeCurrent(pState->display, p->xwindow, p->glxctx);
3729
3730 /* Clean up OpenGL. */
3731 if (p->idReadFramebuffer != OPENGL_INVALID_ID)
3732 pState->ext.glDeleteFramebuffers(1, &p->idReadFramebuffer);
3733 if (p->idDrawFramebuffer != OPENGL_INVALID_ID)
3734 pState->ext.glDeleteFramebuffers(1, &p->idDrawFramebuffer);
3735 if (p->idScreenTexture != OPENGL_INVALID_ID)
3736 glDeleteTextures(1, &p->idScreenTexture);
3737
3738 glXMakeCurrent(pState->display, None, NULL);
3739
3740 glXDestroyContext(pState->display, p->glxctx);
3741 }
3742
3743 if (p->xwindow)
3744 XDestroyWindow(pState->display, p->xwindow);
3745
3746 RT_ZERO(*p);
3747 }
3748}
3749
3750#define GLCHECK() \
3751 do { \
3752 int glErr = glGetError(); \
3753 if (glErr != GL_NO_ERROR) LogRel4(("VMSVGA: GL error 0x%x @%d\n", glErr, __LINE__)); \
3754 } while(0)
3755
3756static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3757{
3758 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: screen %u\n", pScreen->idScreen));
3759
3760 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3761 AssertReturn(pState, VERR_NOT_SUPPORTED);
3762
3763 if (!pThis->svga.f3DOverlayEnabled)
3764 return VERR_NOT_SUPPORTED;
3765
3766 Assert(pScreen->pHwScreen == NULL);
3767
3768 VMSVGAHWSCREEN *p = (VMSVGAHWSCREEN *)RTMemAllocZ(sizeof(VMSVGAHWSCREEN));
3769 AssertPtrReturn(p, VERR_NO_MEMORY);
3770
3771 /* Query the parent window ID from the UI framebuffer.
3772 * If it is there then
3773 * the device will create a texture for the screen content and an overlay window to present the screen content.
3774 * otherwise
3775 * the device will use the guest VRAM system memory for the screen content.
3776 */
3777 Window parentWindow;
3778 int rc = vmsvga3dDrvQueryWindow(pThisCC, pScreen->idScreen, &parentWindow);
3779 if (RT_SUCCESS(rc))
3780 {
3781 /* Create the hardware accelerated screen. */
3782 rc = vmsvga3dHwScreenCreate(pState, parentWindow, pScreen->cWidth, pScreen->cHeight, p);
3783 if (RT_SUCCESS(rc))
3784 {
3785 /*
3786 * Setup the OpenGL context of the screen. The context will be used to draw on the screen.
3787 */
3788
3789 /* GLX context is changed here, so other code has to set the appropriate context again. */
3790 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
3791
3792 Bool const fSuccess = glXMakeCurrent(pState->display, p->xwindow, p->glxctx);
3793 if (fSuccess)
3794 {
3795 /* Set GL state. */
3796 glClearColor(0, 0, 0, 1);
3797 glEnable(GL_TEXTURE_2D);
3798 glDisable(GL_DEPTH_TEST);
3799 glDisable(GL_CULL_FACE);
3800
3801 /* The RGBA texture which hold the screen content. */
3802 glGenTextures(1, &p->idScreenTexture); GLCHECK();
3803 glBindTexture(GL_TEXTURE_2D, p->idScreenTexture); GLCHECK();
3804 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GLCHECK();
3805 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLCHECK();
3806 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, pScreen->cWidth, pScreen->cHeight, 0,
3807 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); GLCHECK();
3808
3809 /* Create read and draw framebuffer objects for this screen. */
3810 pState->ext.glGenFramebuffers(1, &p->idReadFramebuffer); GLCHECK();
3811 pState->ext.glGenFramebuffers(1, &p->idDrawFramebuffer); GLCHECK();
3812
3813 /* Work in screen coordinates. */
3814 glMatrixMode(GL_MODELVIEW);
3815 glLoadIdentity();
3816 glOrtho(0, pScreen->cWidth, 0, pScreen->cHeight, -1, 1);
3817 glMatrixMode(GL_PROJECTION);
3818 glLoadIdentity();
3819
3820 /* Clear the texture. */
3821 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p->idDrawFramebuffer); GLCHECK();
3822 pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3823 p->idScreenTexture, 0); GLCHECK();
3824
3825 glClear(GL_COLOR_BUFFER_BIT);
3826
3827 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); GLCHECK();
3828
3829 glXMakeCurrent(pState->display, None, NULL);
3830
3831 XSync(pState->display, False);
3832
3833 vmsvga3dDrvNotifyHwOverlay(pThisCC, VBOX3D_NOTIFY_TYPE_HW_OVERLAY_CREATED, pScreen->idScreen);
3834 }
3835 else
3836 {
3837 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: failed to set current context\n"));
3838 rc = VERR_NOT_SUPPORTED;
3839 }
3840 }
3841 }
3842 else
3843 {
3844 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: no framebuffer\n"));
3845 }
3846
3847 if (RT_SUCCESS(rc))
3848 {
3849 LogRel(("VMSVGA: Using HW accelerated screen %u\n", pScreen->idScreen));
3850 pScreen->pHwScreen = p;
3851 }
3852 else
3853 {
3854 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: %Rrc\n", rc));
3855 vmsvga3dHwScreenDestroy(pState, p);
3856 RTMemFree(p);
3857 }
3858
3859 return rc;
3860}
3861
3862static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3863{
3864 LogRel4(("VMSVGA: vmsvga3dBackDestroyScreen: screen %u\n", pScreen->idScreen));
3865
3866 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3867 AssertReturn(pState, VERR_NOT_SUPPORTED);
3868
3869 int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
3870
3871 VMSVGAHWSCREEN *p = pScreen->pHwScreen;
3872 if (p)
3873 {
3874 pScreen->pHwScreen = NULL;
3875
3876 vmsvga3dDrvNotifyHwOverlay(pThisCC, VBOX3D_NOTIFY_TYPE_HW_OVERLAY_DESTROYED, pScreen->idScreen);
3877
3878 vmsvga3dHwScreenDestroy(pState, p);
3879 RTMemFree(p);
3880 }
3881
3882 XSetErrorHandler(oldHandler);
3883
3884 return VINF_SUCCESS;
3885}
3886
3887/* Blit a surface to the GLX pixmap. */
3888static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen,
3889 SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage,
3890 SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects)
3891{
3892 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3893 AssertReturn(pState, VERR_NOT_SUPPORTED);
3894
3895 VMSVGAHWSCREEN *p = pScreen->pHwScreen;
3896 AssertReturn(p, VERR_NOT_SUPPORTED);
3897
3898 PVMSVGA3DSURFACE pSurface;
3899 int rc = vmsvga3dSurfaceFromSid(pState, srcImage.sid, &pSurface);
3900 AssertRCReturn(rc, rc);
3901
3902 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
3903 {
3904 LogFunc(("src sid=%u flags=0x%x format=%d -> create texture\n", srcImage.sid, pSurface->f.s.surface1Flags, pSurface->format));
3905 rc = vmsvga3dBackCreateTexture(pThisCC, &pState->SharedCtx, VMSVGA3D_SHARED_CTX_ID, pSurface);
3906 AssertRCReturn(rc, rc);
3907 }
3908
3909 AssertReturn(pSurface->enmOGLResType == VMSVGA3D_OGLRESTYPE_TEXTURE, VERR_NOT_SUPPORTED);
3910
3911 PVMSVGA3DMIPMAPLEVEL pMipLevel;
3912 rc = vmsvga3dMipmapLevel(pSurface, srcImage.face, srcImage.mipmap, &pMipLevel);
3913 AssertRCReturn(rc, rc);
3914
3915 /** @todo Implement. */
3916 RT_NOREF(cRects, paRects);
3917
3918 /* GLX context is changed here, so other code has to set appropriate context again. */
3919 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
3920
3921 int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
3922
3923 Bool fSuccess = glXMakeCurrent(pState->display, p->xwindow, p->glxctx);
3924 if (fSuccess)
3925 {
3926 /* Activate the read and draw framebuffer objects. */
3927 pState->ext.glBindFramebuffer(GL_READ_FRAMEBUFFER, p->idReadFramebuffer); GLCHECK();
3928 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p->idDrawFramebuffer); GLCHECK();
3929
3930 /* Bind the source and destination objects to the right place. */
3931 pState->ext.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3932 pSurface->oglId.texture, 0); GLCHECK();
3933 pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3934 p->idScreenTexture, 0); GLCHECK();
3935
3936 pState->ext.glBlitFramebuffer(srcRect.left,
3937 srcRect.top,
3938 srcRect.right,
3939 srcRect.bottom,
3940 destRect.left,
3941 destRect.top,
3942 destRect.right,
3943 destRect.bottom,
3944 GL_COLOR_BUFFER_BIT,
3945 GL_NEAREST); GLCHECK();
3946
3947 /* Reset the frame buffer association */
3948 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, 0); GLCHECK();
3949
3950 /* Update the overlay window. */
3951 glClear(GL_COLOR_BUFFER_BIT);
3952
3953 glBindTexture(GL_TEXTURE_2D, p->idScreenTexture); GLCHECK();
3954
3955 GLint const w = pScreen->cWidth;
3956 GLint const h = pScreen->cHeight;
3957
3958 glBegin(GL_QUADS);
3959 glTexCoord2f(0.0f, 0.0f); glVertex2i(0, h);
3960 glTexCoord2f(0.0f, 1.0f); glVertex2i(0, 0);
3961 glTexCoord2f(1.0f, 1.0f); glVertex2i(w, 0);
3962 glTexCoord2f(1.0f, 0.0f); glVertex2i(w, h);
3963 glEnd(); GLCHECK();
3964
3965 glBindTexture(GL_TEXTURE_2D, 0); GLCHECK();
3966
3967 glXMakeCurrent(pState->display, None, NULL);
3968 }
3969 else
3970 {
3971 LogRel4(("VMSVGA: vmsvga3dBackSurfaceBlitToScreen: screen %u, glXMakeCurrent for pixmap failed\n", pScreen->idScreen));
3972 }
3973
3974 XSetErrorHandler(oldHandler);
3975
3976 return VINF_SUCCESS;
3977}
3978
3979#else /* !RT_OS_LINUX */
3980
3981static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3982{
3983 RT_NOREF(pThis, pThisCC, pScreen);
3984 return VERR_NOT_IMPLEMENTED;
3985}
3986
3987static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3988{
3989 RT_NOREF(pThisCC, pScreen);
3990 return VERR_NOT_IMPLEMENTED;
3991}
3992
3993static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen,
3994 SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage,
3995 SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects)
3996{
3997 RT_NOREF(pThisCC, pScreen, destRect, srcImage, srcRect, cRects, paRects);
3998 return VERR_NOT_IMPLEMENTED;
3999}
4000#endif
4001
4002/**
4003 * Create a new 3d context
4004 *
4005 * @returns VBox status code.
4006 * @param pThisCC The VGA/VMSVGA state for ring-3.
4007 * @param cid Context id
4008 */
4009static DECLCALLBACK(int) vmsvga3dBackContextDefine(PVGASTATECC pThisCC, uint32_t cid)
4010{
4011 return vmsvga3dContextDefineOgl(pThisCC, cid, 0/*fFlags*/);
4012}
4013
4014/**
4015 * Destroys a 3d context.
4016 *
4017 * @returns VBox status code.
4018 * @param pThisCC The VGA/VMSVGA state for ring-3.
4019 * @param pContext The context to destroy.
4020 * @param cid Context id
4021 */
4022static int vmsvga3dContextDestroyOgl(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid)
4023{
4024 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4025 AssertReturn(pState, VERR_NO_MEMORY);
4026 AssertReturn(pContext, VERR_INVALID_PARAMETER);
4027 AssertReturn(pContext->id == cid, VERR_INVALID_PARAMETER);
4028 Log(("vmsvga3dContextDestroyOgl id %x\n", cid));
4029
4030 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4031
4032 if (pContext->id == VMSVGA3D_SHARED_CTX_ID)
4033 {
4034 /* Delete resources which use the shared context. */
4035 vmsvga3dOnSharedContextDestroy(pState);
4036 }
4037
4038 /* Destroy all leftover pixel shaders. */
4039 for (uint32_t i = 0; i < pContext->cPixelShaders; i++)
4040 {
4041 if (pContext->paPixelShader[i].id != SVGA3D_INVALID_ID)
4042 vmsvga3dBackShaderDestroy(pThisCC, pContext->paPixelShader[i].cid, pContext->paPixelShader[i].id, pContext->paPixelShader[i].type);
4043 }
4044 if (pContext->paPixelShader)
4045 RTMemFree(pContext->paPixelShader);
4046
4047 /* Destroy all leftover vertex shaders. */
4048 for (uint32_t i = 0; i < pContext->cVertexShaders; i++)
4049 {
4050 if (pContext->paVertexShader[i].id != SVGA3D_INVALID_ID)
4051 vmsvga3dBackShaderDestroy(pThisCC, pContext->paVertexShader[i].cid, pContext->paVertexShader[i].id, pContext->paVertexShader[i].type);
4052 }
4053 if (pContext->paVertexShader)
4054 RTMemFree(pContext->paVertexShader);
4055
4056 if (pContext->state.paVertexShaderConst)
4057 RTMemFree(pContext->state.paVertexShaderConst);
4058 if (pContext->state.paPixelShaderConst)
4059 RTMemFree(pContext->state.paPixelShaderConst);
4060
4061 if (pContext->pShaderContext)
4062 {
4063 int rc = ShaderContextDestroy(pContext->pShaderContext);
4064 AssertRC(rc);
4065 }
4066
4067 if (pContext->idFramebuffer != OPENGL_INVALID_ID)
4068 {
4069 /* Unbind the object from the framebuffer target. */
4070 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, 0 /* back buffer */);
4071 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4072 pState->ext.glDeleteFramebuffers(1, &pContext->idFramebuffer);
4073 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4074
4075 if (pContext->idReadFramebuffer != OPENGL_INVALID_ID)
4076 {
4077 pState->ext.glDeleteFramebuffers(1, &pContext->idReadFramebuffer);
4078 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4079 }
4080 if (pContext->idDrawFramebuffer != OPENGL_INVALID_ID)
4081 {
4082 pState->ext.glDeleteFramebuffers(1, &pContext->idDrawFramebuffer);
4083 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4084 }
4085 }
4086
4087 vmsvga3dBackOcclusionQueryDelete(pThisCC, pContext);
4088
4089#ifdef RT_OS_WINDOWS
4090 wglMakeCurrent(pContext->hdc, NULL);
4091 wglDeleteContext(pContext->hglrc);
4092 ReleaseDC(pContext->hwnd, pContext->hdc);
4093
4094 /* Destroy the window we've created. */
4095 int rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_DESTROYWINDOW, (WPARAM)pContext->hwnd, 0);
4096 AssertRC(rc);
4097#elif defined(RT_OS_DARWIN)
4098 vmsvga3dCocoaDestroyViewAndContext(pContext->cocoaView, pContext->cocoaContext);
4099#elif defined(RT_OS_LINUX)
4100 glXMakeCurrent(pState->display, None, NULL);
4101 glXDestroyContext(pState->display, pContext->glxContext);
4102 XDestroyWindow(pState->display, pContext->window);
4103#endif
4104
4105 memset(pContext, 0, sizeof(*pContext));
4106 pContext->id = SVGA3D_INVALID_ID;
4107
4108 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
4109 return VINF_SUCCESS;
4110}
4111
4112/**
4113 * Destroy an existing 3d context
4114 *
4115 * @returns VBox status code.
4116 * @param pThisCC The VGA/VMSVGA state for ring-3.
4117 * @param cid Context id
4118 */
4119static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid)
4120{
4121 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4122 AssertReturn(pState, VERR_WRONG_ORDER);
4123
4124 /*
4125 * Resolve the context and hand it to the common worker function.
4126 */
4127 if ( cid < pState->cContexts
4128 && pState->papContexts[cid]->id == cid)
4129 return vmsvga3dContextDestroyOgl(pThisCC, pState->papContexts[cid], cid);
4130
4131 AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER);
4132 return VINF_SUCCESS;
4133}
4134
4135/**
4136 * Worker for vmsvga3dBackChangeMode that resizes a context.
4137 *
4138 * @param pState The VMSVGA3d state.
4139 * @param pContext The context.
4140 */
4141static void vmsvga3dChangeModeOneContext(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext)
4142{
4143 RT_NOREF(pState, pContext);
4144 /* Do nothing. The window is not used for presenting. */
4145}
4146
4147/* Handle resize */
4148static DECLCALLBACK(int) vmsvga3dBackChangeMode(PVGASTATECC pThisCC)
4149{
4150 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4151 AssertReturn(pState, VERR_NO_MEMORY);
4152
4153 /* Resize the shared context too. */
4154 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
4155 vmsvga3dChangeModeOneContext(pState, &pState->SharedCtx);
4156
4157 /* Resize all active contexts. */
4158 for (uint32_t i = 0; i < pState->cContexts; i++)
4159 {
4160 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
4161 if (pContext->id != SVGA3D_INVALID_ID)
4162 vmsvga3dChangeModeOneContext(pState, pContext);
4163 }
4164
4165 return VINF_SUCCESS;
4166}
4167
4168
4169static DECLCALLBACK(int) vmsvga3dBackSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16])
4170{
4171 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4172 AssertReturn(pState, VERR_NO_MEMORY);
4173 bool fModelViewChanged = false;
4174
4175 Log(("vmsvga3dSetTransform cid=%u %s\n", cid, vmsvgaTransformToString(type)));
4176
4177 ASSERT_GUEST_RETURN((unsigned)type < SVGA3D_TRANSFORM_MAX, VERR_INVALID_PARAMETER);
4178
4179 PVMSVGA3DCONTEXT pContext;
4180 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
4181 AssertRCReturn(rc, rc);
4182
4183 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4184
4185 /* Save this matrix for vm state save/restore. */
4186 pContext->state.aTransformState[type].fValid = true;
4187 memcpy(pContext->state.aTransformState[type].matrix, matrix, sizeof(pContext->state.aTransformState[type].matrix));
4188 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_TRANSFORM;
4189
4190 Log(("Matrix [%d %d %d %d]\n", (int)(matrix[0] * 10.0), (int)(matrix[1] * 10.0), (int)(matrix[2] * 10.0), (int)(matrix[3] * 10.0)));
4191 Log((" [%d %d %d %d]\n", (int)(matrix[4] * 10.0), (int)(matrix[5] * 10.0), (int)(matrix[6] * 10.0), (int)(matrix[7] * 10.0)));
4192 Log((" [%d %d %d %d]\n", (int)(matrix[8] * 10.0), (int)(matrix[9] * 10.0), (int)(matrix[10] * 10.0), (int)(matrix[11] * 10.0)));
4193 Log((" [%d %d %d %d]\n", (int)(matrix[12] * 10.0), (int)(matrix[13] * 10.0), (int)(matrix[14] * 10.0), (int)(matrix[15] * 10.0)));
4194
4195 switch (type)
4196 {
4197 case SVGA3D_TRANSFORM_VIEW:
4198 /* View * World = Model View */
4199 glMatrixMode(GL_MODELVIEW);
4200 glLoadMatrixf(matrix);
4201 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_WORLD].fValid)
4202 glMultMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_WORLD].matrix);
4203 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4204 fModelViewChanged = true;
4205 break;
4206
4207 case SVGA3D_TRANSFORM_PROJECTION:
4208 {
4209 rc = ShaderTransformProjection(pContext->state.RectViewPort.w, pContext->state.RectViewPort.h, matrix, false /* fPretransformed */);
4210 AssertRCReturn(rc, rc);
4211 break;
4212 }
4213
4214 case SVGA3D_TRANSFORM_TEXTURE0:
4215 glMatrixMode(GL_TEXTURE);
4216 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4217 glLoadMatrixf(matrix);
4218 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4219 break;
4220
4221 case SVGA3D_TRANSFORM_TEXTURE1:
4222 case SVGA3D_TRANSFORM_TEXTURE2:
4223 case SVGA3D_TRANSFORM_TEXTURE3:
4224 case SVGA3D_TRANSFORM_TEXTURE4:
4225 case SVGA3D_TRANSFORM_TEXTURE5:
4226 case SVGA3D_TRANSFORM_TEXTURE6:
4227 case SVGA3D_TRANSFORM_TEXTURE7:
4228 Log(("vmsvga3dSetTransform: unsupported SVGA3D_TRANSFORM_TEXTUREx transform!!\n"));
4229 return VERR_INVALID_PARAMETER;
4230
4231 case SVGA3D_TRANSFORM_WORLD:
4232 /* View * World = Model View */
4233 glMatrixMode(GL_MODELVIEW);
4234 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].fValid)
4235 glLoadMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix);
4236 else
4237 glLoadIdentity();
4238 glMultMatrixf(matrix);
4239 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4240 fModelViewChanged = true;
4241 break;
4242
4243 case SVGA3D_TRANSFORM_WORLD1:
4244 case SVGA3D_TRANSFORM_WORLD2:
4245 case SVGA3D_TRANSFORM_WORLD3:
4246 Log(("vmsvga3dSetTransform: unsupported SVGA3D_TRANSFORM_WORLDx transform!!\n"));
4247 return VERR_INVALID_PARAMETER;
4248
4249 default:
4250 Log(("vmsvga3dSetTransform: unknown type!!\n"));
4251 return VERR_INVALID_PARAMETER;
4252 }
4253
4254 /* Apparently we need to reset the light and clip data after modifying the modelview matrix. */
4255 if (fModelViewChanged)
4256 {
4257 /* Reprogram the clip planes. */
4258 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aClipPlane); j++)
4259 {
4260 if (pContext->state.aClipPlane[j].fValid == true)
4261 vmsvga3dBackSetClipPlane(pThisCC, cid, j, pContext->state.aClipPlane[j].plane);
4262 }
4263
4264 /* Reprogram the light data. */
4265 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aLightData); j++)
4266 {
4267 if (pContext->state.aLightData[j].fValidData == true)
4268 vmsvga3dBackSetLightData(pThisCC, cid, j, &pContext->state.aLightData[j].data);
4269 }
4270 }
4271
4272 return VINF_SUCCESS;
4273}
4274
4275static DECLCALLBACK(int) vmsvga3dBackSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange)
4276{
4277 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4278 AssertReturn(pState, VERR_NO_MEMORY);
4279
4280 Log(("vmsvga3dSetZRange cid=%u min=%d max=%d\n", cid, (uint32_t)(zRange.min * 100.0), (uint32_t)(zRange.max * 100.0)));
4281
4282 PVMSVGA3DCONTEXT pContext;
4283 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
4284 AssertRCReturn(rc, rc);
4285
4286 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4287
4288 pContext->state.zRange = zRange;
4289 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_ZRANGE;
4290
4291 if (zRange.min < -1.0)
4292 zRange.min = -1.0;
4293 if (zRange.max > 1.0)
4294 zRange.max = 1.0;
4295
4296 glDepthRange((GLdouble)zRange.min, (GLdouble)zRange.max);
4297 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4298 return VINF_SUCCESS;
4299}
4300
4301/**
4302 * Convert SVGA blend op value to its OpenGL equivalent
4303 */
4304static GLenum vmsvga3dBlendOp2GL(uint32_t blendOp)
4305{
4306 switch (blendOp)
4307 {
4308 case SVGA3D_BLENDOP_ZERO:
4309 return GL_ZERO;
4310 case SVGA3D_BLENDOP_ONE:
4311 return GL_ONE;
4312 case SVGA3D_BLENDOP_SRCCOLOR:
4313 return GL_SRC_COLOR;
4314 case SVGA3D_BLENDOP_INVSRCCOLOR:
4315 return GL_ONE_MINUS_SRC_COLOR;
4316 case SVGA3D_BLENDOP_SRCALPHA:
4317 return GL_SRC_ALPHA;
4318 case SVGA3D_BLENDOP_INVSRCALPHA:
4319 return GL_ONE_MINUS_SRC_ALPHA;
4320 case SVGA3D_BLENDOP_DESTALPHA:
4321 return GL_DST_ALPHA;
4322 case SVGA3D_BLENDOP_INVDESTALPHA:
4323 return GL_ONE_MINUS_DST_ALPHA;
4324 case SVGA3D_BLENDOP_DESTCOLOR:
4325 return GL_DST_COLOR;
4326 case SVGA3D_BLENDOP_INVDESTCOLOR:
4327 return GL_ONE_MINUS_DST_COLOR;
4328 case SVGA3D_BLENDOP_SRCALPHASAT:
4329 return GL_SRC_ALPHA_SATURATE;
4330 case SVGA3D_BLENDOP_BLENDFACTOR:
4331 return GL_CONSTANT_COLOR;
4332 case SVGA3D_BLENDOP_INVBLENDFACTOR:
4333 return GL_ONE_MINUS_CONSTANT_COLOR;
4334 default:
4335 AssertFailed();
4336 return GL_ONE;
4337 }
4338}
4339
4340static GLenum vmsvga3dBlendEquation2GL(uint32_t blendEq)
4341{
4342 switch (blendEq)
4343 {
4344 case SVGA3D_BLENDEQ_ADD:
4345 return GL_FUNC_ADD;
4346 case SVGA3D_BLENDEQ_SUBTRACT:
4347 return GL_FUNC_SUBTRACT;
4348 case SVGA3D_BLENDEQ_REVSUBTRACT:
4349 return GL_FUNC_REVERSE_SUBTRACT;
4350 case SVGA3D_BLENDEQ_MINIMUM:
4351 return GL_MIN;
4352 case SVGA3D_BLENDEQ_MAXIMUM:
4353 return GL_MAX;
4354 default:
4355 /* SVGA3D_BLENDEQ_INVALID means that the render state has not been set, therefore use default. */
4356 AssertMsg(blendEq == SVGA3D_BLENDEQ_INVALID, ("blendEq=%d (%#x)\n", blendEq, blendEq));
4357 return GL_FUNC_ADD;
4358 }
4359}
4360
4361static GLenum vmsvgaCmpFunc2GL(uint32_t cmpFunc)
4362{
4363 switch (cmpFunc)
4364 {
4365 case SVGA3D_CMP_NEVER:
4366 return GL_NEVER;
4367 case SVGA3D_CMP_LESS:
4368 return GL_LESS;
4369 case SVGA3D_CMP_EQUAL:
4370 return GL_EQUAL;
4371 case SVGA3D_CMP_LESSEQUAL:
4372 return GL_LEQUAL;
4373 case SVGA3D_CMP_GREATER:
4374 return GL_GREATER;
4375 case SVGA3D_CMP_NOTEQUAL:
4376 return GL_NOTEQUAL;
4377 case SVGA3D_CMP_GREATEREQUAL:
4378 return GL_GEQUAL;
4379 case SVGA3D_CMP_ALWAYS:
4380 return GL_ALWAYS;
4381 default:
4382 Assert(cmpFunc == SVGA3D_CMP_INVALID);
4383 return GL_LESS;
4384 }
4385}
4386
4387static GLenum vmsvgaStencipOp2GL(uint32_t stencilOp)
4388{
4389 switch (stencilOp)
4390 {
4391 case SVGA3D_STENCILOP_KEEP:
4392 return GL_KEEP;
4393 case SVGA3D_STENCILOP_ZERO:
4394 return GL_ZERO;
4395 case SVGA3D_STENCILOP_REPLACE:
4396 return GL_REPLACE;
4397 case SVGA3D_STENCILOP_INCRSAT:
4398 return GL_INCR_WRAP;
4399 case SVGA3D_STENCILOP_DECRSAT:
4400 return GL_DECR_WRAP;
4401 case SVGA3D_STENCILOP_INVERT:
4402 return GL_INVERT;
4403 case SVGA3D_STENCILOP_INCR:
4404 return GL_INCR;
4405 case SVGA3D_STENCILOP_DECR:
4406 return GL_DECR;
4407 default:
4408 Assert(stencilOp == SVGA3D_STENCILOP_INVALID);
4409 return GL_KEEP;
4410 }
4411}
4412
4413static DECLCALLBACK(int) vmsvga3dBackSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState)
4414{
4415 uint32_t val = UINT32_MAX; /* Shut up MSC. */
4416 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4417 AssertReturn(pState, VERR_NO_MEMORY);
4418
4419 Log(("vmsvga3dSetRenderState cid=%u cRenderStates=%d\n", cid, cRenderStates));
4420
4421 PVMSVGA3DCONTEXT pContext;
4422 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
4423 AssertRCReturn(rc, rc);
4424
4425 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4426
4427 for (unsigned i = 0; i < cRenderStates; i++)
4428 {
4429 GLenum enableCap = ~(GLenum)0;
4430 Log(("vmsvga3dSetRenderState: cid=%u state=%s (%d) val=%x\n", cid, vmsvga3dGetRenderStateName(pRenderState[i].state), pRenderState[i].state, pRenderState[i].uintValue));
4431 /* Save the render state for vm state saving. */
4432 ASSERT_GUEST_RETURN((unsigned)pRenderState[i].state < SVGA3D_RS_MAX, VERR_INVALID_PARAMETER);
4433 pContext->state.aRenderState[pRenderState[i].state] = pRenderState[i];
4434
4435 switch (pRenderState[i].state)
4436 {
4437 case SVGA3D_RS_ZENABLE: /* SVGA3dBool */
4438 enableCap = GL_DEPTH_TEST;
4439 val = pRenderState[i].uintValue;
4440 break;
4441
4442 case SVGA3D_RS_ZWRITEENABLE: /* SVGA3dBool */
4443 glDepthMask(!!pRenderState[i].uintValue);
4444 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4445 break;
4446
4447 case SVGA3D_RS_ALPHATESTENABLE: /* SVGA3dBool */
4448 enableCap = GL_ALPHA_TEST;
4449 val = pRenderState[i].uintValue;
4450 break;
4451
4452 case SVGA3D_RS_DITHERENABLE: /* SVGA3dBool */
4453 enableCap = GL_DITHER;
4454 val = pRenderState[i].uintValue;
4455 break;
4456
4457 case SVGA3D_RS_FOGENABLE: /* SVGA3dBool */
4458 enableCap = GL_FOG;
4459 val = pRenderState[i].uintValue;
4460 break;
4461
4462 case SVGA3D_RS_SPECULARENABLE: /* SVGA3dBool */
4463 Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n"));
4464 break;
4465
4466 case SVGA3D_RS_LIGHTINGENABLE: /* SVGA3dBool */
4467 enableCap = GL_LIGHTING;
4468 val = pRenderState[i].uintValue;
4469 break;
4470
4471 case SVGA3D_RS_NORMALIZENORMALS: /* SVGA3dBool */
4472 /* not applicable */
4473 Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n"));
4474 break;
4475
4476 case SVGA3D_RS_POINTSPRITEENABLE: /* SVGA3dBool */
4477 enableCap = GL_POINT_SPRITE_ARB;
4478 val = pRenderState[i].uintValue;
4479 break;
4480
4481 case SVGA3D_RS_POINTSIZE: /* float */
4482 /** @todo we need to apply scaling for point sizes below the min or above the max; see Wine) */
4483 if (pRenderState[i].floatValue < pState->caps.flPointSize[0])
4484 pRenderState[i].floatValue = pState->caps.flPointSize[0];
4485 if (pRenderState[i].floatValue > pState->caps.flPointSize[1])
4486 pRenderState[i].floatValue = pState->caps.flPointSize[1];
4487
4488 glPointSize(pRenderState[i].floatValue);
4489 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4490 Log(("SVGA3D_RS_POINTSIZE: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
4491 break;
4492
4493 case SVGA3D_RS_POINTSIZEMIN: /* float */
4494 pState->ext.glPointParameterf(GL_POINT_SIZE_MIN, pRenderState[i].floatValue);
4495 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4496 Log(("SVGA3D_RS_POINTSIZEMIN: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
4497 break;
4498
4499 case SVGA3D_RS_POINTSIZEMAX: /* float */
4500 pState->ext.glPointParameterf(GL_POINT_SIZE_MAX, pRenderState[i].floatValue);
4501 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4502 Log(("SVGA3D_RS_POINTSIZEMAX: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
4503 break;
4504
4505 case SVGA3D_RS_POINTSCALEENABLE: /* SVGA3dBool */
4506 case SVGA3D_RS_POINTSCALE_A: /* float */
4507 case SVGA3D_RS_POINTSCALE_B: /* float */
4508 case SVGA3D_RS_POINTSCALE_C: /* float */
4509 Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n"));
4510 break;
4511
4512 case SVGA3D_RS_AMBIENT: /* SVGA3dColor */
4513 {
4514 GLfloat color[4]; /* red, green, blue, alpha */
4515
4516 vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &color[0], &color[1], &color[2], &color[3]);
4517
4518 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color);
4519 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4520 break;
4521 }
4522
4523 case SVGA3D_RS_CLIPPLANEENABLE: /* SVGA3dClipPlanes */
4524 {
4525 for (uint32_t j = 0; j < SVGA3D_NUM_CLIPPLANES; j++)
4526 {
4527 if (pRenderState[i].uintValue & RT_BIT(j))
4528 glEnable(GL_CLIP_PLANE0 + j);
4529 else
4530 glDisable(GL_CLIP_PLANE0 + j);
4531 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4532 }
4533 break;
4534 }
4535
4536 case SVGA3D_RS_FOGCOLOR: /* SVGA3dColor */
4537 {
4538 GLfloat color[4]; /* red, green, blue, alpha */
4539
4540 vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &color[0], &color[1], &color[2], &color[3]);
4541
4542 glFogfv(GL_FOG_COLOR, color);
4543 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4544 break;
4545 }
4546
4547 case SVGA3D_RS_FOGSTART: /* float */
4548 glFogf(GL_FOG_START, pRenderState[i].floatValue);
4549 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4550 break;
4551
4552 case SVGA3D_RS_FOGEND: /* float */
4553 glFogf(GL_FOG_END, pRenderState[i].floatValue);
4554 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4555 break;
4556
4557 case SVGA3D_RS_FOGDENSITY: /* float */
4558 glFogf(GL_FOG_DENSITY, pRenderState[i].floatValue);
4559 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4560 break;
4561
4562 case SVGA3D_RS_RANGEFOGENABLE: /* SVGA3dBool */
4563 glFogi(GL_FOG_COORD_SRC, (pRenderState[i].uintValue) ? GL_FOG_COORD : GL_FRAGMENT_DEPTH);
4564 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4565 break;
4566
4567 case SVGA3D_RS_FOGMODE: /* SVGA3dFogMode */
4568 {
4569 SVGA3dFogMode mode;
4570 mode.uintValue = pRenderState[i].uintValue;
4571
4572 enableCap = GL_FOG_MODE;
4573 switch (mode.function)
4574 {
4575 case SVGA3D_FOGFUNC_EXP:
4576 val = GL_EXP;
4577 break;
4578 case SVGA3D_FOGFUNC_EXP2:
4579 val = GL_EXP2;
4580 break;
4581 case SVGA3D_FOGFUNC_LINEAR:
4582 val = GL_LINEAR;
4583 break;
4584 default:
4585 AssertMsgFailedReturn(("Unexpected fog function %d\n", mode.function), VERR_INTERNAL_ERROR);
4586 break;
4587 }
4588
4589 /** @todo how to switch between vertex and pixel fog modes??? */
4590 Assert(mode.type == SVGA3D_FOGTYPE_PIXEL);
4591#if 0
4592 /* The fog type determines the render state. */
4593 switch (mode.type)
4594 {
4595 case SVGA3D_FOGTYPE_VERTEX:
4596 renderState = D3DRS_FOGVERTEXMODE;
4597 break;
4598 case SVGA3D_FOGTYPE_PIXEL:
4599 renderState = D3DRS_FOGTABLEMODE;
4600 break;
4601 default:
4602 AssertMsgFailedReturn(("Unexpected fog type %d\n", mode.type), VERR_INTERNAL_ERROR);
4603 break;
4604 }
4605#endif
4606
4607 /* Set the fog base to depth or range. */
4608 switch (mode.base)
4609 {
4610 case SVGA3D_FOGBASE_DEPTHBASED:
4611 glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
4612 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4613 break;
4614 case SVGA3D_FOGBASE_RANGEBASED:
4615 glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD);
4616 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4617 break;
4618 default:
4619 /* ignore */
4620 AssertMsgFailed(("Unexpected fog base %d\n", mode.base));
4621 break;
4622 }
4623 break;
4624 }
4625
4626 case SVGA3D_RS_FILLMODE: /* SVGA3dFillMode */
4627 {
4628 SVGA3dFillMode mode;
4629
4630 mode.uintValue = pRenderState[i].uintValue;
4631
4632 switch (mode.mode)
4633 {
4634 case SVGA3D_FILLMODE_POINT:
4635 val = GL_POINT;
4636 break;
4637 case SVGA3D_FILLMODE_LINE:
4638 val = GL_LINE;
4639 break;
4640 case SVGA3D_FILLMODE_FILL:
4641 val = GL_FILL;
4642 break;
4643 default:
4644 AssertMsgFailedReturn(("Unexpected fill mode %d\n", mode.mode), VERR_INTERNAL_ERROR);
4645 break;
4646 }
4647 /* Only front and back faces. Also recent Mesa guest drivers initialize the 'face' to zero. */
4648 ASSERT_GUEST(mode.face == SVGA3D_FACE_FRONT_BACK || mode.face == SVGA3D_FACE_INVALID);
4649 glPolygonMode(GL_FRONT_AND_BACK, val);
4650 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4651 break;
4652 }
4653
4654 case SVGA3D_RS_SHADEMODE: /* SVGA3dShadeMode */
4655 switch (pRenderState[i].uintValue)
4656 {
4657 case SVGA3D_SHADEMODE_FLAT:
4658 val = GL_FLAT;
4659 break;
4660
4661 case SVGA3D_SHADEMODE_SMOOTH:
4662 val = GL_SMOOTH;
4663 break;
4664
4665 default:
4666 AssertMsgFailedReturn(("Unexpected shade mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR);
4667 break;
4668 }
4669
4670 glShadeModel(val);
4671 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4672 break;
4673
4674 case SVGA3D_RS_LINEPATTERN: /* SVGA3dLinePattern */
4675 /* No longer supported by d3d; mesagl comments suggest not all backends support it */
4676 /** @todo */
4677 Log(("WARNING: SVGA3D_RS_LINEPATTERN %x not supported!!\n", pRenderState[i].uintValue));
4678 /*
4679 renderState = D3DRS_LINEPATTERN;
4680 val = pRenderState[i].uintValue;
4681 */
4682 break;
4683
4684 case SVGA3D_RS_ANTIALIASEDLINEENABLE: /* SVGA3dBool */
4685 enableCap = GL_LINE_SMOOTH;
4686 val = pRenderState[i].uintValue;
4687 break;
4688
4689 case SVGA3D_RS_LINEWIDTH: /* float */
4690 glLineWidth(pRenderState[i].floatValue);
4691 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4692 break;
4693
4694 case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */
4695 {
4696 /* Refresh the blending state based on the new enable setting.
4697 * This will take existing states and set them using either glBlend* or glBlend*Separate.
4698 */
4699 static SVGA3dRenderStateName const saRefreshState[] =
4700 {
4701 SVGA3D_RS_SRCBLEND,
4702 SVGA3D_RS_BLENDEQUATION
4703 };
4704 SVGA3dRenderState renderstate[RT_ELEMENTS(saRefreshState)];
4705 for (uint32_t j = 0; j < RT_ELEMENTS(saRefreshState); ++j)
4706 {
4707 renderstate[j].state = saRefreshState[j];
4708 renderstate[j].uintValue = pContext->state.aRenderState[saRefreshState[j]].uintValue;
4709 }
4710
4711 rc = vmsvga3dBackSetRenderState(pThisCC, cid, 2, renderstate);
4712 AssertRCReturn(rc, rc);
4713
4714 if (pContext->state.aRenderState[SVGA3D_RS_BLENDENABLE].uintValue != 0)
4715 continue; /* Ignore if blend is enabled */
4716 /* Apply SVGA3D_RS_SEPARATEALPHABLENDENABLE as SVGA3D_RS_BLENDENABLE */
4717 } RT_FALL_THRU();
4718
4719 case SVGA3D_RS_BLENDENABLE: /* SVGA3dBool */
4720 enableCap = GL_BLEND;
4721 val = pRenderState[i].uintValue;
4722 break;
4723
4724 case SVGA3D_RS_SRCBLENDALPHA: /* SVGA3dBlendOp */
4725 case SVGA3D_RS_DSTBLENDALPHA: /* SVGA3dBlendOp */
4726 case SVGA3D_RS_SRCBLEND: /* SVGA3dBlendOp */
4727 case SVGA3D_RS_DSTBLEND: /* SVGA3dBlendOp */
4728 {
4729 GLint srcRGB, srcAlpha, dstRGB, dstAlpha;
4730 GLint blendop = vmsvga3dBlendOp2GL(pRenderState[i].uintValue);
4731
4732 glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB);
4733 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4734 glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB);
4735 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4736 glGetIntegerv(GL_BLEND_DST_ALPHA, &dstAlpha);
4737 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4738 glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcAlpha);
4739 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4740
4741 switch (pRenderState[i].state)
4742 {
4743 case SVGA3D_RS_SRCBLEND:
4744 srcRGB = blendop;
4745 break;
4746 case SVGA3D_RS_DSTBLEND:
4747 dstRGB = blendop;
4748 break;
4749 case SVGA3D_RS_SRCBLENDALPHA:
4750 srcAlpha = blendop;
4751 break;
4752 case SVGA3D_RS_DSTBLENDALPHA:
4753 dstAlpha = blendop;
4754 break;
4755 default:
4756 /* not possible; shut up gcc */
4757 AssertFailed();
4758 break;
4759 }
4760
4761 if (pContext->state.aRenderState[SVGA3D_RS_SEPARATEALPHABLENDENABLE].uintValue != 0)
4762 pState->ext.glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
4763 else
4764 glBlendFunc(srcRGB, dstRGB);
4765 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4766 break;
4767 }
4768
4769 case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation */
4770 case SVGA3D_RS_BLENDEQUATION: /* SVGA3dBlendEquation */
4771 if (pContext->state.aRenderState[SVGA3D_RS_SEPARATEALPHABLENDENABLE].uintValue != 0)
4772 {
4773 GLenum const modeRGB = vmsvga3dBlendEquation2GL(pContext->state.aRenderState[SVGA3D_RS_BLENDEQUATION].uintValue);
4774 GLenum const modeAlpha = vmsvga3dBlendEquation2GL(pContext->state.aRenderState[SVGA3D_RS_BLENDEQUATIONALPHA].uintValue);
4775 pState->ext.glBlendEquationSeparate(modeRGB, modeAlpha);
4776 }
4777 else
4778 {
4779#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x102
4780 glBlendEquation(vmsvga3dBlendEquation2GL(pRenderState[i].uintValue));
4781#else
4782 pState->ext.glBlendEquation(vmsvga3dBlendEquation2GL(pRenderState[i].uintValue));
4783#endif
4784 }
4785 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4786 break;
4787
4788 case SVGA3D_RS_BLENDCOLOR: /* SVGA3dColor */
4789 {
4790 GLfloat red, green, blue, alpha;
4791
4792 vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &red, &green, &blue, &alpha);
4793
4794#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x102
4795 glBlendColor(red, green, blue, alpha);
4796#else
4797 pState->ext.glBlendColor(red, green, blue, alpha);
4798#endif
4799 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4800 break;
4801 }
4802
4803 case SVGA3D_RS_CULLMODE: /* SVGA3dFace */
4804 {
4805 GLenum mode = GL_BACK; /* default for OpenGL */
4806
4807 switch (pRenderState[i].uintValue)
4808 {
4809 case SVGA3D_FACE_NONE:
4810 break;
4811 case SVGA3D_FACE_FRONT:
4812 mode = GL_FRONT;
4813 break;
4814 case SVGA3D_FACE_BACK:
4815 mode = GL_BACK;
4816 break;
4817 case SVGA3D_FACE_FRONT_BACK:
4818 mode = GL_FRONT_AND_BACK;
4819 break;
4820 default:
4821 AssertMsgFailedReturn(("Unexpected cull mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR);
4822 break;
4823 }
4824 enableCap = GL_CULL_FACE;
4825 if (pRenderState[i].uintValue != SVGA3D_FACE_NONE)
4826 {
4827 glCullFace(mode);
4828 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4829 val = 1;
4830 }
4831 else
4832 val = 0;
4833 break;
4834 }
4835
4836 case SVGA3D_RS_ZFUNC: /* SVGA3dCmpFunc */
4837 glDepthFunc(vmsvgaCmpFunc2GL(pRenderState[i].uintValue));
4838 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4839 break;
4840
4841 case SVGA3D_RS_ALPHAFUNC: /* SVGA3dCmpFunc */
4842 {
4843 GLclampf ref;
4844
4845 glGetFloatv(GL_ALPHA_TEST_REF, &ref);
4846 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4847 glAlphaFunc(vmsvgaCmpFunc2GL(pRenderState[i].uintValue), ref);
4848 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4849 break;
4850 }
4851
4852 case SVGA3D_RS_ALPHAREF: /* float (0.0 .. 1.0) */
4853 {
4854 GLint func;
4855
4856 glGetIntegerv(GL_ALPHA_TEST_FUNC, &func);
4857 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4858 glAlphaFunc(func, pRenderState[i].floatValue);
4859 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4860 break;
4861 }
4862
4863 case SVGA3D_RS_STENCILENABLE2SIDED: /* SVGA3dBool */
4864 {
4865 /* Refresh the stencil state based on the new enable setting.
4866 * This will take existing states and set them using either glStencil or glStencil*Separate.
4867 */
4868 static SVGA3dRenderStateName const saRefreshState[] =
4869 {
4870 SVGA3D_RS_STENCILFUNC,
4871 SVGA3D_RS_STENCILFAIL,
4872 SVGA3D_RS_CCWSTENCILFUNC,
4873 SVGA3D_RS_CCWSTENCILFAIL
4874 };
4875 SVGA3dRenderState renderstate[RT_ELEMENTS(saRefreshState)];
4876 for (uint32_t j = 0; j < RT_ELEMENTS(saRefreshState); ++j)
4877 {
4878 renderstate[j].state = saRefreshState[j];
4879 renderstate[j].uintValue = pContext->state.aRenderState[saRefreshState[j]].uintValue;
4880 }
4881
4882 rc = vmsvga3dBackSetRenderState(pThisCC, cid, RT_ELEMENTS(renderstate), renderstate);
4883 AssertRCReturn(rc, rc);
4884
4885 if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE].uintValue != 0)
4886 continue; /* Ignore if stencil is enabled */
4887 /* Apply SVGA3D_RS_STENCILENABLE2SIDED as SVGA3D_RS_STENCILENABLE. */
4888 } RT_FALL_THRU();
4889
4890 case SVGA3D_RS_STENCILENABLE: /* SVGA3dBool */
4891 enableCap = GL_STENCIL_TEST;
4892 val = pRenderState[i].uintValue;
4893 break;
4894
4895 case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc */
4896 case SVGA3D_RS_STENCILREF: /* uint32_t */
4897 case SVGA3D_RS_STENCILMASK: /* uint32_t */
4898 {
4899 GLint func, ref;
4900 GLuint mask;
4901
4902 /* Query current values to have all parameters for glStencilFunc[Separate]. */
4903 glGetIntegerv(GL_STENCIL_FUNC, &func);
4904 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4905 glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&mask);
4906 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4907 glGetIntegerv(GL_STENCIL_REF, &ref);
4908 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4909
4910 /* Update the changed value. */
4911 switch (pRenderState[i].state)
4912 {
4913 case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc */
4914 func = vmsvgaCmpFunc2GL(pRenderState[i].uintValue);
4915 break;
4916
4917 case SVGA3D_RS_STENCILREF: /* uint32_t */
4918 ref = pRenderState[i].uintValue;
4919 break;
4920
4921 case SVGA3D_RS_STENCILMASK: /* uint32_t */
4922 mask = pRenderState[i].uintValue;
4923 break;
4924
4925 default:
4926 /* not possible; shut up gcc */
4927 AssertFailed();
4928 break;
4929 }
4930
4931 if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE2SIDED].uintValue != 0)
4932 {
4933 pState->ext.glStencilFuncSeparate(GL_FRONT, func, ref, mask);
4934 }
4935 else
4936 {
4937 glStencilFunc(func, ref, mask);
4938 }
4939 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4940 break;
4941 }
4942
4943 case SVGA3D_RS_STENCILWRITEMASK: /* uint32_t */
4944 glStencilMask(pRenderState[i].uintValue);
4945 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4946 break;
4947
4948 case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp */
4949 case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp */
4950 case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp */
4951 {
4952 GLint sfail, dpfail, dppass;
4953 GLenum const stencilop = vmsvgaStencipOp2GL(pRenderState[i].uintValue);
4954
4955 glGetIntegerv(GL_STENCIL_FAIL, &sfail);
4956 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4957 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail);
4958 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4959 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &dppass);
4960 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4961
4962 switch (pRenderState[i].state)
4963 {
4964 case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp */
4965 sfail = stencilop;
4966 break;
4967 case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp */
4968 dpfail = stencilop;
4969 break;
4970 case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp */
4971 dppass = stencilop;
4972 break;
4973 default:
4974 /* not possible; shut up gcc */
4975 AssertFailed();
4976 break;
4977 }
4978 if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE2SIDED].uintValue != 0)
4979 {
4980 pState->ext.glStencilOpSeparate(GL_FRONT, sfail, dpfail, dppass);
4981 }
4982 else
4983 {
4984 glStencilOp(sfail, dpfail, dppass);
4985 }
4986 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4987 break;
4988 }
4989
4990 case SVGA3D_RS_CCWSTENCILFUNC: /* SVGA3dCmpFunc */
4991 {
4992 GLint ref;
4993 GLuint mask;
4994 GLint const func = vmsvgaCmpFunc2GL(pRenderState[i].uintValue);
4995
4996 /* GL_STENCIL_VALUE_MASK and GL_STENCIL_REF are the same for both GL_FRONT and GL_BACK. */
4997 glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&mask);
4998 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4999 glGetIntegerv(GL_STENCIL_REF, &ref);
5000 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5001
5002 pState->ext.glStencilFuncSeparate(GL_BACK, func, ref, mask);
5003 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5004 break;
5005 }
5006
5007 case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp */
5008 case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp */
5009 case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp */
5010 {
5011 GLint sfail, dpfail, dppass;
5012 GLenum const stencilop = vmsvgaStencipOp2GL(pRenderState[i].uintValue);
5013
5014 glGetIntegerv(GL_STENCIL_BACK_FAIL, &sfail);
5015 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5016 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &dpfail);
5017 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5018 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &dppass);
5019 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5020
5021 switch (pRenderState[i].state)
5022 {
5023 case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp */
5024 sfail = stencilop;
5025 break;
5026 case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp */
5027 dpfail = stencilop;
5028 break;
5029 case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp */
5030 dppass = stencilop;
5031 break;
5032 default:
5033 /* not possible; shut up gcc */
5034 AssertFailed();
5035 break;
5036 }
5037 pState->ext.glStencilOpSeparate(GL_BACK, sfail, dpfail, dppass);
5038 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5039 break;
5040 }
5041
5042 case SVGA3D_RS_ZBIAS: /* float */
5043 /** @todo unknown meaning; depth bias is not identical
5044 renderState = D3DRS_DEPTHBIAS;
5045 val = pRenderState[i].uintValue;
5046 */
5047 Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_RS_ZBIAS\n"));
5048 break;
5049
5050 case SVGA3D_RS_DEPTHBIAS: /* float */
5051 {
5052 GLfloat factor;
5053
5054 /** @todo not sure if the d3d & ogl definitions are identical. */
5055
5056 /* Do not change the factor part. */
5057 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &factor);
5058 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5059
5060 glPolygonOffset(factor, pRenderState[i].floatValue);
5061 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5062 break;
5063 }
5064
5065 case SVGA3D_RS_SLOPESCALEDEPTHBIAS: /* float */
5066 {
5067 GLfloat units;
5068
5069 /** @todo not sure if the d3d & ogl definitions are identical. */
5070
5071 /* Do not change the factor part. */
5072 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &units);
5073 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5074
5075 glPolygonOffset(pRenderState[i].floatValue, units);
5076 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5077 break;
5078 }
5079
5080 case SVGA3D_RS_COLORWRITEENABLE: /* SVGA3dColorMask */
5081 {
5082 GLboolean red, green, blue, alpha;
5083 SVGA3dColorMask mask;
5084
5085 mask.uintValue = pRenderState[i].uintValue;
5086
5087 red = mask.red;
5088 green = mask.green;
5089 blue = mask.blue;
5090 alpha = mask.alpha;
5091
5092 glColorMask(red, green, blue, alpha);
5093 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5094 break;
5095 }
5096
5097 case SVGA3D_RS_COLORWRITEENABLE1: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */
5098 case SVGA3D_RS_COLORWRITEENABLE2: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */
5099 case SVGA3D_RS_COLORWRITEENABLE3: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */
5100 Log(("vmsvga3dSetRenderState: WARNING SVGA3D_RS_COLORWRITEENABLEx not supported!!\n"));
5101 break;
5102
5103 case SVGA3D_RS_SCISSORTESTENABLE: /* SVGA3dBool */
5104 enableCap = GL_SCISSOR_TEST;
5105 val = pRenderState[i].uintValue;
5106 break;
5107
5108#if 0
5109 case SVGA3D_RS_DIFFUSEMATERIALSOURCE: /* SVGA3dVertexMaterial */
5110 AssertCompile(D3DMCS_COLOR2 == SVGA3D_VERTEXMATERIAL_SPECULAR);
5111 renderState = D3DRS_DIFFUSEMATERIALSOURCE;
5112 val = pRenderState[i].uintValue;
5113 break;
5114
5115 case SVGA3D_RS_SPECULARMATERIALSOURCE: /* SVGA3dVertexMaterial */
5116 renderState = D3DRS_SPECULARMATERIALSOURCE;
5117 val = pRenderState[i].uintValue;
5118 break;
5119
5120 case SVGA3D_RS_AMBIENTMATERIALSOURCE: /* SVGA3dVertexMaterial */
5121 renderState = D3DRS_AMBIENTMATERIALSOURCE;
5122 val = pRenderState[i].uintValue;
5123 break;
5124
5125 case SVGA3D_RS_EMISSIVEMATERIALSOURCE: /* SVGA3dVertexMaterial */
5126 renderState = D3DRS_EMISSIVEMATERIALSOURCE;
5127 val = pRenderState[i].uintValue;
5128 break;
5129#endif
5130
5131 case SVGA3D_RS_WRAP3: /* SVGA3dWrapFlags */
5132 case SVGA3D_RS_WRAP4: /* SVGA3dWrapFlags */
5133 case SVGA3D_RS_WRAP5: /* SVGA3dWrapFlags */
5134 case SVGA3D_RS_WRAP6: /* SVGA3dWrapFlags */
5135 case SVGA3D_RS_WRAP7: /* SVGA3dWrapFlags */
5136 case SVGA3D_RS_WRAP8: /* SVGA3dWrapFlags */
5137 case SVGA3D_RS_WRAP9: /* SVGA3dWrapFlags */
5138 case SVGA3D_RS_WRAP10: /* SVGA3dWrapFlags */
5139 case SVGA3D_RS_WRAP11: /* SVGA3dWrapFlags */
5140 case SVGA3D_RS_WRAP12: /* SVGA3dWrapFlags */
5141 case SVGA3D_RS_WRAP13: /* SVGA3dWrapFlags */
5142 case SVGA3D_RS_WRAP14: /* SVGA3dWrapFlags */
5143 case SVGA3D_RS_WRAP15: /* SVGA3dWrapFlags */
5144 Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_WRAPx (x >= 3)\n"));
5145 break;
5146
5147 case SVGA3D_RS_LASTPIXEL: /* SVGA3dBool */
5148 case SVGA3D_RS_TWEENFACTOR: /* float */
5149 case SVGA3D_RS_INDEXEDVERTEXBLENDENABLE: /* SVGA3dBool */
5150 case SVGA3D_RS_VERTEXBLEND: /* SVGA3dVertexBlendFlags */
5151 Log(("vmsvga3dSetRenderState: WARNING not applicable!!\n"));
5152 break;
5153
5154 case SVGA3D_RS_MULTISAMPLEANTIALIAS: /* SVGA3dBool */
5155 enableCap = GL_MULTISAMPLE;
5156 val = pRenderState[i].uintValue;
5157 break;
5158
5159 case SVGA3D_RS_MULTISAMPLEMASK: /* uint32_t */
5160 Log(("vmsvga3dSetRenderState: WARNING not applicable??!!\n"));
5161 break;
5162
5163 case SVGA3D_RS_COORDINATETYPE: /* SVGA3dCoordinateType */
5164 Assert(pRenderState[i].uintValue == SVGA3D_COORDINATE_LEFTHANDED);
5165 /** @todo setup a view matrix to scale the world space by -1 in the z-direction for right handed coordinates. */
5166 /*
5167 renderState = D3DRS_COORDINATETYPE;
5168 val = pRenderState[i].uintValue;
5169 */
5170 break;
5171
5172 case SVGA3D_RS_FRONTWINDING: /* SVGA3dFrontWinding */
5173 Assert(pRenderState[i].uintValue == SVGA3D_FRONTWINDING_CW);
5174 /* Invert the selected mode because of y-inversion (?) */
5175 glFrontFace((pRenderState[i].uintValue != SVGA3D_FRONTWINDING_CW) ? GL_CW : GL_CCW);
5176 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5177 break;
5178
5179 case SVGA3D_RS_OUTPUTGAMMA: /* float */
5180 //AssertFailed();
5181 /*
5182 D3DRS_SRGBWRITEENABLE ??
5183 renderState = D3DRS_OUTPUTGAMMA;
5184 val = pRenderState[i].uintValue;
5185 */
5186 break;
5187
5188#if 0
5189
5190 case SVGA3D_RS_VERTEXMATERIALENABLE: /* SVGA3dBool */
5191 //AssertFailed();
5192 renderState = D3DRS_INDEXEDVERTEXBLENDENABLE; /* correct?? */
5193 val = pRenderState[i].uintValue;
5194 break;
5195
5196 case SVGA3D_RS_TEXTUREFACTOR: /* SVGA3dColor */
5197 renderState = D3DRS_TEXTUREFACTOR;
5198 val = pRenderState[i].uintValue;
5199 break;
5200
5201 case SVGA3D_RS_LOCALVIEWER: /* SVGA3dBool */
5202 renderState = D3DRS_LOCALVIEWER;
5203 val = pRenderState[i].uintValue;
5204 break;
5205
5206 case SVGA3D_RS_ZVISIBLE: /* SVGA3dBool */
5207 AssertFailed();
5208 /*
5209 renderState = D3DRS_ZVISIBLE;
5210 val = pRenderState[i].uintValue;
5211 */
5212 break;
5213
5214 case SVGA3D_RS_CLIPPING: /* SVGA3dBool */
5215 renderState = D3DRS_CLIPPING;
5216 val = pRenderState[i].uintValue;
5217 break;
5218
5219 case SVGA3D_RS_WRAP0: /* SVGA3dWrapFlags */
5220 glTexParameter GL_TEXTURE_WRAP_S
5221 Assert(SVGA3D_WRAPCOORD_3 == D3DWRAPCOORD_3);
5222 renderState = D3DRS_WRAP0;
5223 val = pRenderState[i].uintValue;
5224 break;
5225
5226 case SVGA3D_RS_WRAP1: /* SVGA3dWrapFlags */
5227 glTexParameter GL_TEXTURE_WRAP_T
5228 renderState = D3DRS_WRAP1;
5229 val = pRenderState[i].uintValue;
5230 break;
5231
5232 case SVGA3D_RS_WRAP2: /* SVGA3dWrapFlags */
5233 glTexParameter GL_TEXTURE_WRAP_R
5234 renderState = D3DRS_WRAP2;
5235 val = pRenderState[i].uintValue;
5236 break;
5237
5238
5239 case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */
5240 renderState = D3DRS_SEPARATEALPHABLENDENABLE;
5241 val = pRenderState[i].uintValue;
5242 break;
5243
5244
5245 case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation */
5246 renderState = D3DRS_BLENDOPALPHA;
5247 val = pRenderState[i].uintValue;
5248 break;
5249
5250 case SVGA3D_RS_TRANSPARENCYANTIALIAS: /* SVGA3dTransparencyAntialiasType */
5251 AssertFailed();
5252 /*
5253 renderState = D3DRS_TRANSPARENCYANTIALIAS;
5254 val = pRenderState[i].uintValue;
5255 */
5256 break;
5257
5258#endif
5259 default:
5260 AssertFailed();
5261 break;
5262 }
5263
5264 if (enableCap != ~(GLenum)0)
5265 {
5266 if (val)
5267 glEnable(enableCap);
5268 else
5269 glDisable(enableCap);
5270 }
5271 }
5272
5273 return VINF_SUCCESS;
5274}
5275
5276static DECLCALLBACK(int) vmsvga3dBackSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target)
5277{
5278 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5279
5280 AssertReturn(pState, VERR_NO_MEMORY);
5281 AssertReturn((unsigned)type < SVGA3D_RT_MAX, VERR_INVALID_PARAMETER);
5282
5283 LogFunc(("cid=%u type=%x sid=%u\n", cid, type, target.sid));
5284
5285 PVMSVGA3DCONTEXT pContext;
5286 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
5287 AssertRCReturn(rc, rc);
5288
5289 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5290
5291 /* Save for vm state save/restore. */
5292 pContext->state.aRenderTargets[type] = target.sid;
5293
5294 if (target.sid == SVGA3D_INVALID_ID)
5295 {
5296 /* Disable render target. */
5297 switch (type)
5298