VirtualBox

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

Last change on this file was 99775, checked in by vboxsync, 12 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 {
5299 case SVGA3D_RT_DEPTH:
5300 case SVGA3D_RT_STENCIL:
5301 pState->ext.glFramebufferRenderbuffer(GL_FRAMEBUFFER, (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
5302 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5303 break;
5304
5305 case SVGA3D_RT_COLOR0:
5306 case SVGA3D_RT_COLOR1:
5307 case SVGA3D_RT_COLOR2:
5308 case SVGA3D_RT_COLOR3:
5309 case SVGA3D_RT_COLOR4:
5310 case SVGA3D_RT_COLOR5:
5311 case SVGA3D_RT_COLOR6:
5312 case SVGA3D_RT_COLOR7:
5313 pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + type - SVGA3D_RT_COLOR0, 0, 0, 0);
5314 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5315 break;
5316
5317 default:
5318 AssertFailedReturn(VERR_INVALID_PARAMETER);
5319 }
5320 return VINF_SUCCESS;
5321 }
5322
5323 PVMSVGA3DSURFACE pRenderTarget;
5324 rc = vmsvga3dSurfaceFromSid(pState, target.sid, &pRenderTarget);
5325 AssertRCReturn(rc, rc);
5326
5327 switch (type)
5328 {
5329 case SVGA3D_RT_DEPTH:
5330 case SVGA3D_RT_STENCIL:
5331#if 1
5332 /* A texture surface can be used as a render target to fill it and later on used as a texture. */
5333 if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID)
5334 {
5335 LogFunc(("create depth texture to be used as render target; surface id=%x type=%d format=%d -> create texture\n",
5336 target.sid, pRenderTarget->f.s.surface1Flags, pRenderTarget->format));
5337 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget);
5338 AssertRCReturn(rc, rc);
5339 }
5340
5341 AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER);
5342 Assert(!pRenderTarget->fDirty);
5343
5344 pRenderTarget->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
5345
5346 pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER,
5347 (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT,
5348 GL_TEXTURE_2D, pRenderTarget->oglId.texture, target.mipmap);
5349 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5350#else
5351 AssertReturn(target.mipmap == 0, VERR_INVALID_PARAMETER);
5352 if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID)
5353 {
5354 Log(("vmsvga3dSetRenderTarget: create renderbuffer to be used as render target; surface id=%x type=%d format=%d\n", target.sid, pRenderTarget->f.s.surface1Flags, pRenderTarget->internalFormatGL));
5355 pContext = &pState->SharedCtx;
5356 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5357
5358 pState->ext.glGenRenderbuffers(1, &pRenderTarget->oglId.renderbuffer);
5359 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5360 pSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_RENDERBUFFER;
5361
5362 pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer);
5363 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5364
5365 pState->ext.glRenderbufferStorage(GL_RENDERBUFFER,
5366 pRenderTarget->internalFormatGL,
5367 pRenderTarget->paMipmapLevels[0].mipmapSize.width,
5368 pRenderTarget->paMipmapLevels[0].mipmapSize.height);
5369 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5370
5371 pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, OPENGL_INVALID_ID);
5372 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5373
5374 pContext = pState->papContexts[cid];
5375 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5376 }
5377
5378 pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer);
5379 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5380 Assert(!pRenderTarget->fDirty);
5381 AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER);
5382
5383 pRenderTarget->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
5384
5385 pState->ext.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
5386 (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT,
5387 GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer);
5388 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5389#endif
5390 break;
5391
5392 case SVGA3D_RT_COLOR0:
5393 case SVGA3D_RT_COLOR1:
5394 case SVGA3D_RT_COLOR2:
5395 case SVGA3D_RT_COLOR3:
5396 case SVGA3D_RT_COLOR4:
5397 case SVGA3D_RT_COLOR5:
5398 case SVGA3D_RT_COLOR6:
5399 case SVGA3D_RT_COLOR7:
5400 {
5401 /* A texture surface can be used as a render target to fill it and later on used as a texture. */
5402 if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID)
5403 {
5404 Log(("vmsvga3dSetRenderTarget: create texture to be used as render target; surface id=%x type=%d format=%d -> create texture\n", target.sid, pRenderTarget->f.s.surface1Flags, pRenderTarget->format));
5405 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget);
5406 AssertRCReturn(rc, rc);
5407 }
5408
5409 AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER);
5410 Assert(!pRenderTarget->fDirty);
5411
5412 pRenderTarget->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
5413
5414 GLenum textarget;
5415 if (pRenderTarget->f.s.surface1Flags & SVGA3D_SURFACE_CUBEMAP)
5416 textarget = vmsvga3dCubemapFaceFromIndex(target.face);
5417 else
5418 textarget = GL_TEXTURE_2D;
5419 pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + type - SVGA3D_RT_COLOR0,
5420 textarget, pRenderTarget->oglId.texture, target.mipmap);
5421 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5422
5423#ifdef DEBUG
5424 GLenum status = pState->ext.glCheckFramebufferStatus(GL_FRAMEBUFFER);
5425 if (status != GL_FRAMEBUFFER_COMPLETE)
5426 Log(("vmsvga3dSetRenderTarget: WARNING: glCheckFramebufferStatus returned %x\n", status));
5427#endif
5428 /** @todo use glDrawBuffers too? */
5429 break;
5430 }
5431
5432 default:
5433 AssertFailedReturn(VERR_INVALID_PARAMETER);
5434 }
5435
5436 return VINF_SUCCESS;
5437}
5438
5439#if 0
5440/**
5441 * Convert SVGA texture combiner value to its D3D equivalent
5442 */
5443static DWORD vmsvga3dTextureCombiner2D3D(uint32_t value)
5444{
5445 switch (value)
5446 {
5447 case SVGA3D_TC_DISABLE:
5448 return D3DTOP_DISABLE;
5449 case SVGA3D_TC_SELECTARG1:
5450 return D3DTOP_SELECTARG1;
5451 case SVGA3D_TC_SELECTARG2:
5452 return D3DTOP_SELECTARG2;
5453 case SVGA3D_TC_MODULATE:
5454 return D3DTOP_MODULATE;
5455 case SVGA3D_TC_ADD:
5456 return D3DTOP_ADD;
5457 case SVGA3D_TC_ADDSIGNED:
5458 return D3DTOP_ADDSIGNED;
5459 case SVGA3D_TC_SUBTRACT:
5460 return D3DTOP_SUBTRACT;
5461 case SVGA3D_TC_BLENDTEXTUREALPHA:
5462 return D3DTOP_BLENDTEXTUREALPHA;
5463 case SVGA3D_TC_BLENDDIFFUSEALPHA:
5464 return D3DTOP_BLENDDIFFUSEALPHA;
5465 case SVGA3D_TC_BLENDCURRENTALPHA:
5466 return D3DTOP_BLENDCURRENTALPHA;
5467 case SVGA3D_TC_BLENDFACTORALPHA:
5468 return D3DTOP_BLENDFACTORALPHA;
5469 case SVGA3D_TC_MODULATE2X:
5470 return D3DTOP_MODULATE2X;
5471 case SVGA3D_TC_MODULATE4X:
5472 return D3DTOP_MODULATE4X;
5473 case SVGA3D_TC_DSDT:
5474 AssertFailed(); /** @todo ??? */
5475 return D3DTOP_DISABLE;
5476 case SVGA3D_TC_DOTPRODUCT3:
5477 return D3DTOP_DOTPRODUCT3;
5478 case SVGA3D_TC_BLENDTEXTUREALPHAPM:
5479 return D3DTOP_BLENDTEXTUREALPHAPM;
5480 case SVGA3D_TC_ADDSIGNED2X:
5481 return D3DTOP_ADDSIGNED2X;
5482 case SVGA3D_TC_ADDSMOOTH:
5483 return D3DTOP_ADDSMOOTH;
5484 case SVGA3D_TC_PREMODULATE:
5485 return D3DTOP_PREMODULATE;
5486 case SVGA3D_TC_MODULATEALPHA_ADDCOLOR:
5487 return D3DTOP_MODULATEALPHA_ADDCOLOR;
5488 case SVGA3D_TC_MODULATECOLOR_ADDALPHA:
5489 return D3DTOP_MODULATECOLOR_ADDALPHA;
5490 case SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR:
5491 return D3DTOP_MODULATEINVALPHA_ADDCOLOR;
5492 case SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA:
5493 return D3DTOP_MODULATEINVCOLOR_ADDALPHA;
5494 case SVGA3D_TC_BUMPENVMAPLUMINANCE:
5495 return D3DTOP_BUMPENVMAPLUMINANCE;
5496 case SVGA3D_TC_MULTIPLYADD:
5497 return D3DTOP_MULTIPLYADD;
5498 case SVGA3D_TC_LERP:
5499 return D3DTOP_LERP;
5500 default:
5501 AssertFailed();
5502 return D3DTOP_DISABLE;
5503 }
5504}
5505
5506/**
5507 * Convert SVGA texture arg data value to its D3D equivalent
5508 */
5509static DWORD vmsvga3dTextureArgData2D3D(uint32_t value)
5510{
5511 switch (value)
5512 {
5513 case SVGA3D_TA_CONSTANT:
5514 return D3DTA_CONSTANT;
5515 case SVGA3D_TA_PREVIOUS:
5516 return D3DTA_CURRENT; /* current = previous */
5517 case SVGA3D_TA_DIFFUSE:
5518 return D3DTA_DIFFUSE;
5519 case SVGA3D_TA_TEXTURE:
5520 return D3DTA_TEXTURE;
5521 case SVGA3D_TA_SPECULAR:
5522 return D3DTA_SPECULAR;
5523 default:
5524 AssertFailed();
5525 return 0;
5526 }
5527}
5528
5529/**
5530 * Convert SVGA texture transform flag value to its D3D equivalent
5531 */
5532static DWORD vmsvga3dTextTransformFlags2D3D(uint32_t value)
5533{
5534 switch (value)
5535 {
5536 case SVGA3D_TEX_TRANSFORM_OFF:
5537 return D3DTTFF_DISABLE;
5538 case SVGA3D_TEX_TRANSFORM_S:
5539 return D3DTTFF_COUNT1; /** @todo correct? */
5540 case SVGA3D_TEX_TRANSFORM_T:
5541 return D3DTTFF_COUNT2; /** @todo correct? */
5542 case SVGA3D_TEX_TRANSFORM_R:
5543 return D3DTTFF_COUNT3; /** @todo correct? */
5544 case SVGA3D_TEX_TRANSFORM_Q:
5545 return D3DTTFF_COUNT4; /** @todo correct? */
5546 case SVGA3D_TEX_PROJECTED:
5547 return D3DTTFF_PROJECTED;
5548 default:
5549 AssertFailed();
5550 return 0;
5551 }
5552}
5553#endif
5554
5555static GLenum vmsvga3dTextureAddress2OGL(SVGA3dTextureAddress value)
5556{
5557 switch (value)
5558 {
5559 case SVGA3D_TEX_ADDRESS_WRAP:
5560 return GL_REPEAT;
5561 case SVGA3D_TEX_ADDRESS_MIRROR:
5562 return GL_MIRRORED_REPEAT;
5563 case SVGA3D_TEX_ADDRESS_CLAMP:
5564 return GL_CLAMP_TO_EDGE;
5565 case SVGA3D_TEX_ADDRESS_BORDER:
5566 return GL_CLAMP_TO_BORDER;
5567 case SVGA3D_TEX_ADDRESS_MIRRORONCE:
5568 AssertFailed();
5569 return GL_CLAMP_TO_EDGE_SGIS; /** @todo correct? */
5570
5571 case SVGA3D_TEX_ADDRESS_EDGE:
5572 case SVGA3D_TEX_ADDRESS_INVALID:
5573 default:
5574 AssertFailed();
5575 return GL_REPEAT; /* default */
5576 }
5577}
5578
5579static GLenum vmsvga3dTextureFilter2OGL(SVGA3dTextureFilter value)
5580{
5581 switch (value)
5582 {
5583 case SVGA3D_TEX_FILTER_NONE:
5584 case SVGA3D_TEX_FILTER_LINEAR:
5585 case SVGA3D_TEX_FILTER_ANISOTROPIC: /* Anisotropic filtering is controlled by SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL */
5586 return GL_LINEAR;
5587 case SVGA3D_TEX_FILTER_NEAREST:
5588 return GL_NEAREST;
5589 case SVGA3D_TEX_FILTER_FLATCUBIC: // Deprecated, not implemented
5590 case SVGA3D_TEX_FILTER_GAUSSIANCUBIC: // Deprecated, not implemented
5591 case SVGA3D_TEX_FILTER_PYRAMIDALQUAD: // Not currently implemented
5592 case SVGA3D_TEX_FILTER_GAUSSIANQUAD: // Not currently implemented
5593 default:
5594 AssertFailed();
5595 return GL_LINEAR; /* default */
5596 }
5597}
5598
5599#if 0 /* unused */
5600static uint32_t vmsvga3dSVGA3dColor2RGBA(SVGA3dColor value)
5601{
5602 /* flip the red and blue bytes */
5603 uint8_t blue = value & 0xff;
5604 uint8_t red = (value >> 16) & 0xff;
5605 return (value & 0xff00ff00) | red | (blue << 16);
5606}
5607#endif
5608
5609static DECLCALLBACK(int) vmsvga3dBackSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState)
5610{
5611 GLenum val = ~(GLenum)0; /* Shut up MSC. */
5612 GLenum currentStage = ~(GLenum)0;
5613 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5614 AssertReturn(pState, VERR_NO_MEMORY);
5615
5616 Log(("vmsvga3dSetTextureState %x cTextureState=%d\n", cid, cTextureStates));
5617
5618 PVMSVGA3DCONTEXT pContext;
5619 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
5620 AssertRCReturn(rc, rc);
5621
5622 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5623
5624 /* Which texture is active for the current stage. Needed to use right OpenGL target when setting parameters. */
5625 PVMSVGA3DSURFACE pCurrentTextureSurface = NULL;
5626
5627 for (uint32_t i = 0; i < cTextureStates; ++i)
5628 {
5629 GLenum textureType = ~(GLenum)0;
5630#if 0
5631 GLenum samplerType = ~(GLenum)0;
5632#endif
5633
5634 LogFunc(("cid=%u stage=%d type=%s (%x) val=%x\n",
5635 cid, pTextureState[i].stage, vmsvga3dTextureStateToString(pTextureState[i].name), pTextureState[i].name, pTextureState[i].value));
5636
5637 /* Record the texture state for vm state saving. */
5638 if ( pTextureState[i].stage < RT_ELEMENTS(pContext->state.aTextureStates)
5639 && (unsigned)pTextureState[i].name < RT_ELEMENTS(pContext->state.aTextureStates[0]))
5640 {
5641 pContext->state.aTextureStates[pTextureState[i].stage][pTextureState[i].name] = pTextureState[i];
5642 }
5643
5644 /* Activate the right texture unit for subsequent texture state changes. */
5645 if (pTextureState[i].stage != currentStage || i == 0)
5646 {
5647 /** @todo Is this the appropriate limit for all kinds of textures? It is the
5648 * size of aSidActiveTextures and for binding/unbinding we cannot exceed it. */
5649 if (pTextureState[i].stage < RT_ELEMENTS(pContext->state.aTextureStates))
5650 {
5651 pState->ext.glActiveTexture(GL_TEXTURE0 + pTextureState[i].stage);
5652 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5653 currentStage = pTextureState[i].stage;
5654 }
5655 else
5656 {
5657 AssertMsgFailed(("pTextureState[%d].stage=%#x name=%#x\n", i, pTextureState[i].stage, pTextureState[i].name));
5658 continue;
5659 }
5660
5661 if (pContext->aSidActiveTextures[currentStage] != SVGA3D_INVALID_ID)
5662 {
5663 rc = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[currentStage], &pCurrentTextureSurface);
5664 AssertRCReturn(rc, rc);
5665 }
5666 else
5667 pCurrentTextureSurface = NULL; /* Make sure that no stale pointer is used. */
5668 }
5669
5670 switch (pTextureState[i].name)
5671 {
5672 case SVGA3D_TS_BUMPENVMAT00: /* float */
5673 case SVGA3D_TS_BUMPENVMAT01: /* float */
5674 case SVGA3D_TS_BUMPENVMAT10: /* float */
5675 case SVGA3D_TS_BUMPENVMAT11: /* float */
5676 case SVGA3D_TS_BUMPENVLSCALE: /* float */
5677 case SVGA3D_TS_BUMPENVLOFFSET: /* float */
5678 Log(("vmsvga3dSetTextureState: bump mapping texture options not supported!!\n"));
5679 break;
5680
5681 case SVGA3D_TS_COLOROP: /* SVGA3dTextureCombiner */
5682 case SVGA3D_TS_COLORARG0: /* SVGA3dTextureArgData */
5683 case SVGA3D_TS_COLORARG1: /* SVGA3dTextureArgData */
5684 case SVGA3D_TS_COLORARG2: /* SVGA3dTextureArgData */
5685 case SVGA3D_TS_ALPHAOP: /* SVGA3dTextureCombiner */
5686 case SVGA3D_TS_ALPHAARG0: /* SVGA3dTextureArgData */
5687 case SVGA3D_TS_ALPHAARG1: /* SVGA3dTextureArgData */
5688 case SVGA3D_TS_ALPHAARG2: /* SVGA3dTextureArgData */
5689 /** @todo not used by MesaGL */
5690 Log(("vmsvga3dSetTextureState: colorop/alphaop not yet supported!!\n"));
5691 break;
5692#if 0
5693
5694 case SVGA3D_TS_TEXCOORDINDEX: /* uint32_t */
5695 textureType = D3DTSS_TEXCOORDINDEX;
5696 val = pTextureState[i].value;
5697 break;
5698
5699 case SVGA3D_TS_TEXTURETRANSFORMFLAGS: /* SVGA3dTexTransformFlags */
5700 textureType = D3DTSS_TEXTURETRANSFORMFLAGS;
5701 val = vmsvga3dTextTransformFlags2D3D(pTextureState[i].value);
5702 break;
5703#endif
5704
5705 case SVGA3D_TS_BIND_TEXTURE: /* SVGA3dSurfaceId */
5706 {
5707 uint32_t const sid = pTextureState[i].value;
5708
5709 Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%u replacing sid=%u\n",
5710 currentStage, sid, pContext->aSidActiveTextures[currentStage]));
5711
5712 /* Only if texture actually changed. */ /// @todo needs testing.
5713 if (pContext->aSidActiveTextures[currentStage] != sid)
5714 {
5715 if (pCurrentTextureSurface)
5716 {
5717 /* Unselect the currently associated texture. */
5718 glBindTexture(pCurrentTextureSurface->targetGL, 0);
5719 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5720
5721 if (currentStage < 8)
5722 {
5723 /* Necessary for the fixed pipeline. */
5724 glDisable(pCurrentTextureSurface->targetGL);
5725 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5726 }
5727
5728 pCurrentTextureSurface = NULL;
5729 }
5730
5731 if (sid == SVGA3D_INVALID_ID)
5732 {
5733 Assert(pCurrentTextureSurface == NULL);
5734 }
5735 else
5736 {
5737 PVMSVGA3DSURFACE pSurface;
5738 rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
5739 AssertRCReturn(rc, rc);
5740
5741 Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%u (%d,%d) replacing sid=%u\n",
5742 currentStage, sid, pSurface->paMipmapLevels[0].mipmapSize.width,
5743 pSurface->paMipmapLevels[0].mipmapSize.height, pContext->aSidActiveTextures[currentStage]));
5744
5745 if (pSurface->oglId.texture == OPENGL_INVALID_ID)
5746 {
5747 Log(("CreateTexture (%d,%d) levels=%d\n",
5748 pSurface->paMipmapLevels[0].mipmapSize.width, pSurface->paMipmapLevels[0].mipmapSize.height, pSurface->cLevels));
5749 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface);
5750 AssertRCReturn(rc, rc);
5751 }
5752
5753 glBindTexture(pSurface->targetGL, pSurface->oglId.texture);
5754 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5755
5756 if (currentStage < 8)
5757 {
5758 /* Necessary for the fixed pipeline. */
5759 glEnable(pSurface->targetGL);
5760 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5761 }
5762
5763 /* Remember the currently active texture. */
5764 pCurrentTextureSurface = pSurface;
5765
5766 /* Recreate the texture state as glBindTexture resets them all (sigh). */
5767 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); iStage++)
5768 {
5769 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); j++)
5770 {
5771 SVGA3dTextureState *pTextureStateIter = &pContext->state.aTextureStates[iStage][j];
5772
5773 if ( pTextureStateIter->name != SVGA3D_TS_INVALID
5774 && pTextureStateIter->name != SVGA3D_TS_BIND_TEXTURE)
5775 vmsvga3dBackSetTextureState(pThisCC, pContext->id, 1, pTextureStateIter);
5776 }
5777 }
5778 }
5779
5780 pContext->aSidActiveTextures[currentStage] = sid;
5781 }
5782
5783 /* Finished; continue with the next one. */
5784 continue;
5785 }
5786
5787 case SVGA3D_TS_ADDRESSW: /* SVGA3dTextureAddress */
5788 textureType = GL_TEXTURE_WRAP_R; /* R = W */
5789 val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value);
5790 break;
5791
5792 case SVGA3D_TS_ADDRESSU: /* SVGA3dTextureAddress */
5793 textureType = GL_TEXTURE_WRAP_S; /* S = U */
5794 val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value);
5795 break;
5796
5797 case SVGA3D_TS_ADDRESSV: /* SVGA3dTextureAddress */
5798 textureType = GL_TEXTURE_WRAP_T; /* T = V */
5799 val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value);
5800 break;
5801
5802 case SVGA3D_TS_MIPFILTER: /* SVGA3dTextureFilter */
5803 case SVGA3D_TS_MINFILTER: /* SVGA3dTextureFilter */
5804 {
5805 uint32_t mipFilter = pContext->state.aTextureStates[currentStage][SVGA3D_TS_MIPFILTER].value;
5806 uint32_t minFilter = pContext->state.aTextureStates[currentStage][SVGA3D_TS_MINFILTER].value;
5807
5808 /* If SVGA3D_TS_MIPFILTER is set to NONE, then use SVGA3D_TS_MIPFILTER, otherwise SVGA3D_TS_MIPFILTER enables mipmap minification. */
5809 textureType = GL_TEXTURE_MIN_FILTER;
5810 if (mipFilter != SVGA3D_TEX_FILTER_NONE)
5811 {
5812 if (minFilter == SVGA3D_TEX_FILTER_NEAREST)
5813 {
5814 if (mipFilter == SVGA3D_TEX_FILTER_LINEAR)
5815 val = GL_NEAREST_MIPMAP_LINEAR;
5816 else
5817 val = GL_NEAREST_MIPMAP_NEAREST;
5818 }
5819 else
5820 {
5821 if (mipFilter == SVGA3D_TEX_FILTER_LINEAR)
5822 val = GL_LINEAR_MIPMAP_LINEAR;
5823 else
5824 val = GL_LINEAR_MIPMAP_NEAREST;
5825 }
5826 }
5827 else
5828 val = vmsvga3dTextureFilter2OGL((SVGA3dTextureFilter)minFilter);
5829 break;
5830 }
5831
5832 case SVGA3D_TS_MAGFILTER: /* SVGA3dTextureFilter */
5833 textureType = GL_TEXTURE_MAG_FILTER;
5834 val = vmsvga3dTextureFilter2OGL((SVGA3dTextureFilter)pTextureState[i].value);
5835 Assert(val == GL_NEAREST || val == GL_LINEAR);
5836 break;
5837
5838 case SVGA3D_TS_BORDERCOLOR: /* SVGA3dColor */
5839 {
5840 GLfloat color[4]; /* red, green, blue, alpha */
5841 vmsvgaColor2GLFloatArray(pTextureState[i].value, &color[0], &color[1], &color[2], &color[3]);
5842
5843 GLenum targetGL;
5844 if (pCurrentTextureSurface)
5845 targetGL = pCurrentTextureSurface->targetGL;
5846 else
5847 {
5848 /* No texture bound, assume 2D. */
5849 targetGL = GL_TEXTURE_2D;
5850 }
5851
5852 glTexParameterfv(targetGL, GL_TEXTURE_BORDER_COLOR, color); /* Identical; default 0.0 identical too */
5853 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5854 break;
5855 }
5856
5857 case SVGA3D_TS_TEXTURE_LOD_BIAS: /* float */
5858 {
5859 GLenum targetGL;
5860 if (pCurrentTextureSurface)
5861 targetGL = pCurrentTextureSurface->targetGL;
5862 else
5863 {
5864 /* No texture bound, assume 2D. */
5865 targetGL = GL_TEXTURE_2D;
5866 }
5867
5868 glTexParameterf(targetGL, GL_TEXTURE_LOD_BIAS, pTextureState[i].floatValue); /* Identical; default 0.0 identical too */
5869 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5870 break;
5871 }
5872
5873 case SVGA3D_TS_TEXTURE_MIPMAP_LEVEL: /* uint32_t */
5874 textureType = GL_TEXTURE_BASE_LEVEL;
5875 val = pTextureState[i].value;
5876 break;
5877
5878 case SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL: /* uint32_t */
5879 if (pState->caps.fTextureFilterAnisotropicSupported)
5880 {
5881 textureType = GL_TEXTURE_MAX_ANISOTROPY_EXT;
5882 val = RT_MIN((GLint)pTextureState[i].value, pState->caps.maxTextureAnisotropy);
5883 } /* otherwise ignore. */
5884 break;
5885
5886#if 0
5887 case SVGA3D_TS_GAMMA: /* float */
5888 samplerType = D3DSAMP_SRGBTEXTURE;
5889 /* Boolean in D3D */
5890 if (pTextureState[i].floatValue == 1.0f)
5891 val = FALSE;
5892 else
5893 val = TRUE;
5894 break;
5895#endif
5896 /* Internal commands, that don't map directly to the SetTextureStageState API. */
5897 case SVGA3D_TS_TEXCOORDGEN: /* SVGA3dTextureCoordGen */
5898 AssertFailed();
5899 break;
5900
5901 default:
5902 //AssertFailed();
5903 break;
5904 }
5905
5906 if (textureType != ~(GLenum)0)
5907 {
5908 GLenum targetGL;
5909 if (pCurrentTextureSurface)
5910 targetGL = pCurrentTextureSurface->targetGL;
5911 else
5912 {
5913 /* No texture bound, assume 2D. */
5914 targetGL = GL_TEXTURE_2D;
5915 }
5916
5917 switch (pTextureState[i].name)
5918 {
5919 case SVGA3D_TS_MINFILTER:
5920 case SVGA3D_TS_MAGFILTER:
5921 {
5922 if (pState->caps.fTextureFilterAnisotropicSupported)
5923 {
5924 uint32_t const anisotropyLevel = (SVGA3dTextureFilter)pTextureState[i].value == SVGA3D_TEX_FILTER_ANISOTROPIC
5925 ? RT_MAX(1, pContext->state.aTextureStates[currentStage][SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL].value)
5926 : 1;
5927 glTexParameteri(targetGL, GL_TEXTURE_MAX_ANISOTROPY_EXT, RT_MIN((GLint)anisotropyLevel, pState->caps.maxTextureAnisotropy));
5928 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5929 }
5930 } break;
5931
5932 default: break;
5933 }
5934
5935 glTexParameteri(targetGL, textureType, val);
5936 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5937 }
5938 }
5939
5940 return VINF_SUCCESS;
5941}
5942
5943static DECLCALLBACK(int) vmsvga3dBackSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial)
5944{
5945 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5946 AssertReturn(pState, VERR_NO_MEMORY);
5947
5948 LogFunc(("cid=%u face %d\n", cid, face));
5949
5950 PVMSVGA3DCONTEXT pContext;
5951 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
5952 AssertRCReturn(rc, rc);
5953
5954 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5955
5956 GLenum oglFace;
5957 switch (face)
5958 {
5959 case SVGA3D_FACE_NONE:
5960 case SVGA3D_FACE_FRONT:
5961 oglFace = GL_FRONT;
5962 break;
5963
5964 case SVGA3D_FACE_BACK:
5965 oglFace = GL_BACK;
5966 break;
5967
5968 case SVGA3D_FACE_FRONT_BACK:
5969 oglFace = GL_FRONT_AND_BACK;
5970 break;
5971
5972 default:
5973 AssertFailedReturn(VERR_INVALID_PARAMETER);
5974 }
5975
5976 /* Save for vm state save/restore. */
5977 pContext->state.aMaterial[face].fValid = true;
5978 pContext->state.aMaterial[face].material = *pMaterial;
5979 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_MATERIAL;
5980
5981 glMaterialfv(oglFace, GL_DIFFUSE, pMaterial->diffuse);
5982 glMaterialfv(oglFace, GL_AMBIENT, pMaterial->ambient);
5983 glMaterialfv(oglFace, GL_SPECULAR, pMaterial->specular);
5984 glMaterialfv(oglFace, GL_EMISSION, pMaterial->emissive);
5985 glMaterialfv(oglFace, GL_SHININESS, &pMaterial->shininess);
5986 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5987
5988 return VINF_SUCCESS;
5989}
5990
5991/** @todo Move into separate library as we are using logic from Wine here. */
5992static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData)
5993{
5994 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5995 AssertReturn(pState, VERR_NO_MEMORY);
5996
5997 LogFunc(("vmsvga3dSetLightData cid=%u index=%d type=%d\n", cid, index, pData->type));
5998 ASSERT_GUEST_RETURN(index < SVGA3D_MAX_LIGHTS, VERR_INVALID_PARAMETER);
5999
6000 PVMSVGA3DCONTEXT pContext;
6001 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6002 AssertRCReturn(rc, rc);
6003
6004 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6005
6006 /* Store for vm state save/restore */
6007 pContext->state.aLightData[index].fValidData = true;
6008 pContext->state.aLightData[index].data = *pData;
6009
6010 if ( pData->attenuation0 < 0.0f
6011 || pData->attenuation1 < 0.0f
6012 || pData->attenuation2 < 0.0f)
6013 {
6014 Log(("vmsvga3dSetLightData: invalid negative attenuation values!!\n"));
6015 return VINF_SUCCESS; /* ignore; could crash the GL driver */
6016 }
6017
6018 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d */
6019 glMatrixMode(GL_MODELVIEW);
6020 glPushMatrix();
6021 glLoadMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix);
6022
6023 glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, pData->diffuse);
6024 glLightfv(GL_LIGHT0 + index, GL_SPECULAR, pData->specular);
6025 glLightfv(GL_LIGHT0 + index, GL_AMBIENT, pData->ambient);
6026
6027 float QuadAttenuation;
6028 if (pData->range * pData->range >= FLT_MIN)
6029 QuadAttenuation = 1.4f / (pData->range * pData->range);
6030 else
6031 QuadAttenuation = 0.0f;
6032
6033 switch (pData->type)
6034 {
6035 case SVGA3D_LIGHTTYPE_POINT:
6036 {
6037 GLfloat position[4];
6038
6039 position[0] = pData->position[0];
6040 position[1] = pData->position[1];
6041 position[2] = pData->position[2];
6042 position[3] = 1.0f;
6043
6044 glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
6045 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6046
6047 glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
6048 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6049
6050 /* Attenuation - Are these right? guessing... */
6051 glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, pData->attenuation0);
6052 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6053
6054 glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, pData->attenuation1);
6055 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6056
6057 glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, (QuadAttenuation < pData->attenuation2) ? pData->attenuation2 : QuadAttenuation);
6058 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6059
6060 /** @todo range */
6061 break;
6062 }
6063
6064 case SVGA3D_LIGHTTYPE_SPOT1:
6065 {
6066 GLfloat exponent;
6067 GLfloat position[4];
6068 const GLfloat pi = 4.0f * atanf(1.0f);
6069
6070 position[0] = pData->position[0];
6071 position[1] = pData->position[1];
6072 position[2] = pData->position[2];
6073 position[3] = 1.0f;
6074
6075 glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
6076 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6077
6078 position[0] = pData->direction[0];
6079 position[1] = pData->direction[1];
6080 position[2] = pData->direction[2];
6081 position[3] = 1.0f;
6082
6083 glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, position);
6084 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6085
6086 /*
6087 * opengl-ish and d3d-ish spot lights use too different models for the
6088 * light "intensity" as a function of the angle towards the main light direction,
6089 * so we only can approximate very roughly.
6090 * however spot lights are rather rarely used in games (if ever used at all).
6091 * furthermore if still used, probably nobody pays attention to such details.
6092 */
6093 if (pData->falloff == 0)
6094 {
6095 /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
6096 * falloff resp. exponent parameter as an exponent, so the spot light lighting
6097 * will always be 1.0 for both of them, and we don't have to care for the
6098 * rest of the rather complex calculation
6099 */
6100 exponent = 0.0f;
6101 }
6102 else
6103 {
6104 float rho = pData->theta + (pData->phi - pData->theta) / (2 * pData->falloff);
6105 if (rho < 0.0001f)
6106 rho = 0.0001f;
6107 exponent = -0.3f/log(cos(rho/2));
6108 }
6109 if (exponent > 128.0f)
6110 exponent = 128.0f;
6111
6112 glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, exponent);
6113 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6114
6115 glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, pData->phi * 90.0 / pi);
6116 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6117
6118 /* Attenuation - Are these right? guessing... */
6119 glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, pData->attenuation0);
6120 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6121
6122 glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, pData->attenuation1);
6123 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6124
6125 glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, (QuadAttenuation < pData->attenuation2) ? pData->attenuation2 : QuadAttenuation);
6126 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6127
6128 /** @todo range */
6129 break;
6130 }
6131
6132 case SVGA3D_LIGHTTYPE_DIRECTIONAL:
6133 {
6134 GLfloat position[4];
6135
6136 position[0] = -pData->direction[0];
6137 position[1] = -pData->direction[1];
6138 position[2] = -pData->direction[2];
6139 position[3] = 0.0f;
6140
6141 glLightfv(GL_LIGHT0 + index, GL_POSITION, position); /* Note gl uses w position of 0 for direction! */
6142 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6143
6144 glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
6145 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6146
6147 glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, 0.0f);
6148 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6149 break;
6150 }
6151
6152 case SVGA3D_LIGHTTYPE_SPOT2:
6153 default:
6154 Log(("Unsupported light type!!\n"));
6155 rc = VERR_INVALID_PARAMETER;
6156 break;
6157 }
6158
6159 /* Restore the modelview matrix */
6160 glPopMatrix();
6161
6162 return rc;
6163}
6164
6165static DECLCALLBACK(int) vmsvga3dBackSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled)
6166{
6167 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6168 AssertReturn(pState, VERR_NO_MEMORY);
6169
6170 LogFunc(("cid=%u %d -> %d\n", cid, index, enabled));
6171
6172 PVMSVGA3DCONTEXT pContext;
6173 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6174 AssertRCReturn(rc, rc);
6175
6176 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6177
6178 /* Store for vm state save/restore */
6179 if (index < SVGA3D_MAX_LIGHTS)
6180 pContext->state.aLightData[index].fEnabled = !!enabled;
6181 else
6182 AssertFailed();
6183
6184 if (enabled)
6185 {
6186 if (index < SVGA3D_MAX_LIGHTS)
6187 {
6188 /* Load the default settings if none have been set yet. */
6189 if (!pContext->state.aLightData[index].fValidData)
6190 vmsvga3dBackSetLightData(pThisCC, cid, index, (SVGA3dLightData *)&vmsvga3d_default_light);
6191 }
6192 glEnable(GL_LIGHT0 + index);
6193 }
6194 else
6195 glDisable(GL_LIGHT0 + index);
6196
6197 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6198 return VINF_SUCCESS;
6199}
6200
6201static DECLCALLBACK(int) vmsvga3dBackSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)
6202{
6203 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6204 AssertReturn(pState, VERR_NO_MEMORY);
6205
6206 Log(("vmsvga3dSetViewPort cid=%u (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h));
6207
6208 PVMSVGA3DCONTEXT pContext;
6209 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6210 AssertRCReturn(rc, rc);
6211
6212 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6213
6214 /* Save for vm state save/restore. */
6215 pContext->state.RectViewPort = *pRect;
6216 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VIEWPORT;
6217
6218 /** @todo y-inversion for partial viewport coordinates? */
6219 glViewport(pRect->x, pRect->y, pRect->w, pRect->h);
6220 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6221
6222 /* Reset the projection matrix as that relies on the viewport setting. */
6223 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].fValid == true)
6224 vmsvga3dBackSetTransform(pThisCC, cid, SVGA3D_TRANSFORM_PROJECTION,
6225 pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].matrix);
6226 else
6227 {
6228 float matrix[16];
6229
6230 /* identity matrix if no matrix set. */
6231 memset(matrix, 0, sizeof(matrix));
6232 matrix[0] = 1.0;
6233 matrix[5] = 1.0;
6234 matrix[10] = 1.0;
6235 matrix[15] = 1.0;
6236 vmsvga3dBackSetTransform(pThisCC, cid, SVGA3D_TRANSFORM_PROJECTION, matrix);
6237 }
6238
6239 return VINF_SUCCESS;
6240}
6241
6242static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4])
6243{
6244 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6245 AssertReturn(pState, VERR_NO_MEMORY);
6246 double oglPlane[4];
6247
6248 Log(("vmsvga3dSetClipPlane cid=%u %d (%d,%d)(%d,%d)\n", cid, index, (unsigned)(plane[0] * 100.0), (unsigned)(plane[1] * 100.0), (unsigned)(plane[2] * 100.0), (unsigned)(plane[3] * 100.0)));
6249 AssertReturn(index < SVGA3D_NUM_CLIPPLANES, VERR_INVALID_PARAMETER);
6250
6251 PVMSVGA3DCONTEXT pContext;
6252 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6253 AssertRCReturn(rc, rc);
6254
6255 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6256
6257 /* Store for vm state save/restore. */
6258 pContext->state.aClipPlane[index].fValid = true;
6259 memcpy(pContext->state.aClipPlane[index].plane, plane, sizeof(pContext->state.aClipPlane[index].plane));
6260
6261 /** @todo clip plane affected by model view in OpenGL & view in D3D + vertex shader -> not transformed (see Wine; state.c clipplane) */
6262 oglPlane[0] = (double)plane[0];
6263 oglPlane[1] = (double)plane[1];
6264 oglPlane[2] = (double)plane[2];
6265 oglPlane[3] = (double)plane[3];
6266
6267 glClipPlane(GL_CLIP_PLANE0 + index, oglPlane);
6268 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6269
6270 return VINF_SUCCESS;
6271}
6272
6273static DECLCALLBACK(int) vmsvga3dBackSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)
6274{
6275 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6276 AssertReturn(pState, VERR_NO_MEMORY);
6277
6278 Log(("vmsvga3dSetScissorRect cid=%u (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h));
6279
6280 PVMSVGA3DCONTEXT pContext;
6281 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6282 AssertRCReturn(rc, rc);
6283
6284 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6285
6286 /* Store for vm state save/restore. */
6287 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_SCISSORRECT;
6288 pContext->state.RectScissor = *pRect;
6289
6290 glScissor(pRect->x, pRect->y, pRect->w, pRect->h);
6291 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6292
6293 return VINF_SUCCESS;
6294}
6295
6296static void vmsvgaColor2GLFloatArray(uint32_t color, GLfloat *pRed, GLfloat *pGreen, GLfloat *pBlue, GLfloat *pAlpha)
6297{
6298 /* Convert byte color components to float (0-1.0) */
6299 *pAlpha = (GLfloat)(color >> 24) / 255.0;
6300 *pRed = (GLfloat)((color >> 16) & 0xff) / 255.0;
6301 *pGreen = (GLfloat)((color >> 8) & 0xff) / 255.0;
6302 *pBlue = (GLfloat)(color & 0xff) / 255.0;
6303}
6304
6305static DECLCALLBACK(int) vmsvga3dBackCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil,
6306 uint32_t cRects, SVGA3dRect *pRect)
6307{
6308 GLbitfield mask = 0;
6309 GLbitfield restoreMask = 0;
6310 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6311 AssertReturn(pState, VERR_NO_MEMORY);
6312 GLboolean fDepthWriteEnabled = GL_FALSE;
6313 GLboolean afColorWriteEnabled[4] = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE };
6314
6315 Log(("vmsvga3dCommandClear cid=%u clearFlag=%x color=%x depth=%d stencil=%x cRects=%d\n", cid, clearFlag, color, (uint32_t)(depth * 100.0), stencil, cRects));
6316
6317 PVMSVGA3DCONTEXT pContext;
6318 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6319 AssertRCReturn(rc, rc);
6320
6321 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6322
6323 if (clearFlag & SVGA3D_CLEAR_COLOR)
6324 {
6325 GLfloat red, green, blue, alpha;
6326 vmsvgaColor2GLFloatArray(color, &red, &green, &blue, &alpha);
6327
6328 /* Set the color clear value. */
6329 glClearColor(red, green, blue, alpha);
6330 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6331
6332 mask |= GL_COLOR_BUFFER_BIT;
6333
6334 /* glClear will not clear the color buffer if writing is disabled. */
6335 glGetBooleanv(GL_COLOR_WRITEMASK, afColorWriteEnabled);
6336 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6337 if ( afColorWriteEnabled[0] == GL_FALSE
6338 || afColorWriteEnabled[1] == GL_FALSE
6339 || afColorWriteEnabled[2] == GL_FALSE
6340 || afColorWriteEnabled[3] == GL_FALSE)
6341 {
6342 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6343 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6344
6345 restoreMask |= GL_COLOR_BUFFER_BIT;
6346 }
6347
6348 }
6349
6350 if (clearFlag & SVGA3D_CLEAR_STENCIL)
6351 {
6352 /** @todo possibly the same problem as with glDepthMask */
6353 glClearStencil(stencil);
6354 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6355
6356 mask |= GL_STENCIL_BUFFER_BIT;
6357 }
6358
6359 if (clearFlag & SVGA3D_CLEAR_DEPTH)
6360 {
6361 glClearDepth((GLdouble)depth);
6362 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6363
6364 mask |= GL_DEPTH_BUFFER_BIT;
6365
6366 /* glClear will not clear the depth buffer if writing is disabled. */
6367 glGetBooleanv(GL_DEPTH_WRITEMASK, &fDepthWriteEnabled);
6368 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6369 if (fDepthWriteEnabled == GL_FALSE)
6370 {
6371 glDepthMask(GL_TRUE);
6372 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6373
6374 restoreMask |= GL_DEPTH_BUFFER_BIT;
6375 }
6376 }
6377
6378 /* Save the current scissor test bit and scissor box. */
6379 glPushAttrib(GL_SCISSOR_BIT);
6380 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6381
6382 if (cRects)
6383 {
6384 glEnable(GL_SCISSOR_TEST);
6385 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6386
6387 for (uint32_t i = 0; i < cRects; ++i)
6388 {
6389 LogFunc(("rect [%d] %d,%d %dx%d)\n", i, pRect[i].x, pRect[i].y, pRect[i].w, pRect[i].h));
6390 glScissor(pRect[i].x, pRect[i].y, pRect[i].w, pRect[i].h);
6391 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6392
6393 glClear(mask);
6394 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6395 }
6396 }
6397 else
6398 {
6399 glDisable(GL_SCISSOR_TEST);
6400 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6401
6402 glClear(mask);
6403 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6404 }
6405
6406 /* Restore the old scissor test bit and box */
6407 glPopAttrib();
6408 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6409
6410 /* Restore the write states. */
6411 if (restoreMask & GL_COLOR_BUFFER_BIT)
6412 {
6413 glColorMask(afColorWriteEnabled[0],
6414 afColorWriteEnabled[1],
6415 afColorWriteEnabled[2],
6416 afColorWriteEnabled[3]);
6417 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6418 }
6419
6420 if (restoreMask & GL_DEPTH_BUFFER_BIT)
6421 {
6422 glDepthMask(fDepthWriteEnabled);
6423 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6424 }
6425
6426 return VINF_SUCCESS;
6427}
6428
6429/* Convert VMWare vertex declaration to its OpenGL equivalent. */
6430static int vmsvga3dVertexDecl2OGL(SVGA3dVertexArrayIdentity &identity, GLint &size, GLenum &type, GLboolean &normalized, uint32_t &cbAttrib)
6431{
6432 normalized = GL_FALSE;
6433 switch (identity.type)
6434 {
6435 case SVGA3D_DECLTYPE_FLOAT1:
6436 size = 1;
6437 type = GL_FLOAT;
6438 cbAttrib = sizeof(float);
6439 break;
6440 case SVGA3D_DECLTYPE_FLOAT2:
6441 size = 2;
6442 type = GL_FLOAT;
6443 cbAttrib = 2 * sizeof(float);
6444 break;
6445 case SVGA3D_DECLTYPE_FLOAT3:
6446 size = 3;
6447 type = GL_FLOAT;
6448 cbAttrib = 3 * sizeof(float);
6449 break;
6450 case SVGA3D_DECLTYPE_FLOAT4:
6451 size = 4;
6452 type = GL_FLOAT;
6453 cbAttrib = 4 * sizeof(float);
6454 break;
6455
6456 case SVGA3D_DECLTYPE_D3DCOLOR:
6457 size = GL_BGRA; /* @note requires GL_ARB_vertex_array_bgra */
6458 type = GL_UNSIGNED_BYTE;
6459 normalized = GL_TRUE; /* glVertexAttribPointer fails otherwise */
6460 cbAttrib = sizeof(uint32_t);
6461 break;
6462
6463 case SVGA3D_DECLTYPE_UBYTE4N:
6464 normalized = GL_TRUE;
6465 RT_FALL_THRU();
6466 case SVGA3D_DECLTYPE_UBYTE4:
6467 size = 4;
6468 type = GL_UNSIGNED_BYTE;
6469 cbAttrib = sizeof(uint32_t);
6470 break;
6471
6472 case SVGA3D_DECLTYPE_SHORT2N:
6473 normalized = GL_TRUE;
6474 RT_FALL_THRU();
6475 case SVGA3D_DECLTYPE_SHORT2:
6476 size = 2;
6477 type = GL_SHORT;
6478 cbAttrib = 2 * sizeof(uint16_t);
6479 break;
6480
6481 case SVGA3D_DECLTYPE_SHORT4N:
6482 normalized = GL_TRUE;
6483 RT_FALL_THRU();
6484 case SVGA3D_DECLTYPE_SHORT4:
6485 size = 4;
6486 type = GL_SHORT;
6487 cbAttrib = 4 * sizeof(uint16_t);
6488 break;
6489
6490 case SVGA3D_DECLTYPE_USHORT4N:
6491 normalized = GL_TRUE;
6492 size = 4;
6493 type = GL_UNSIGNED_SHORT;
6494 cbAttrib = 4 * sizeof(uint16_t);
6495 break;
6496
6497 case SVGA3D_DECLTYPE_USHORT2N:
6498 normalized = GL_TRUE;
6499 size = 2;
6500 type = GL_UNSIGNED_SHORT;
6501 cbAttrib = 2 * sizeof(uint16_t);
6502 break;
6503
6504 case SVGA3D_DECLTYPE_UDEC3:
6505 size = 3;
6506 type = GL_UNSIGNED_INT_2_10_10_10_REV; /** @todo correct? */
6507 cbAttrib = sizeof(uint32_t);
6508 break;
6509
6510 case SVGA3D_DECLTYPE_DEC3N:
6511 normalized = true;
6512 size = 3;
6513 type = GL_INT_2_10_10_10_REV; /** @todo correct? */
6514 cbAttrib = sizeof(uint32_t);
6515 break;
6516
6517 case SVGA3D_DECLTYPE_FLOAT16_2:
6518 size = 2;
6519 type = GL_HALF_FLOAT;
6520 cbAttrib = 2 * sizeof(uint16_t);
6521 break;
6522 case SVGA3D_DECLTYPE_FLOAT16_4:
6523 size = 4;
6524 type = GL_HALF_FLOAT;
6525 cbAttrib = 4 * sizeof(uint16_t);
6526 break;
6527 default:
6528 AssertFailedReturn(VERR_INVALID_PARAMETER);
6529 }
6530
6531 //pVertexElement->Method = identity.method;
6532 //pVertexElement->Usage = identity.usage;
6533
6534 return VINF_SUCCESS;
6535}
6536
6537static float vmsvga3dFloat16To32(uint16_t f16)
6538{
6539 /* From Wiki */
6540#ifndef INFINITY
6541 static uint32_t const sBitsINFINITY = UINT32_C(0x7f800000);
6542 #define INFINITY (*(float const *)&sBitsINFINITY)
6543#endif
6544#ifndef NAN
6545 static uint32_t const sBitsNAN = UINT32_C(0x7fc00000);
6546 #define NAN (*(float const *)&sBitsNAN)
6547#endif
6548
6549 uint16_t const s = (f16 >> UINT16_C(15)) & UINT16_C(0x1);
6550 uint16_t const e = (f16 >> UINT16_C(10)) & UINT16_C(0x1f);
6551 uint16_t const m = (f16 ) & UINT16_C(0x3ff);
6552
6553 float result = s ? 1.0f : -1.0f;
6554 if (e == 0)
6555 {
6556 if (m == 0)
6557 result *= 0.0f; /* zero, -0 */
6558 else
6559 result *= (float)m / 1024.0f / 16384.0f; /* subnormal numbers: sign * 2^-14 * 0.m */
6560 }
6561 else if (e == 0x1f)
6562 {
6563 if (m == 0)
6564 result *= INFINITY; /* +-infinity */
6565 else
6566 result = NAN; /* NAN */
6567 }
6568 else
6569 {
6570 result *= powf(2.0f, (float)e - 15.0f) * (1.0f + (float)m / 1024.0f); /* sign * 2^(e-15) * 1.m */
6571 }
6572
6573 return result;
6574}
6575
6576/* Set a vertex attribute according to VMSVGA vertex declaration. */
6577static int vmsvga3dSetVertexAttrib(PVMSVGA3DSTATE pState, GLuint index, SVGA3dVertexArrayIdentity const *pIdentity, GLvoid const *pv)
6578{
6579 switch (pIdentity->type)
6580 {
6581 case SVGA3D_DECLTYPE_FLOAT1:
6582 {
6583 /* "One-component float expanded to (float, 0, 0, 1)." */
6584 GLfloat const *p = (GLfloat *)pv;
6585 GLfloat const v[4] = { p[0], 0.0f, 0.0f, 1.0f };
6586 pState->ext.glVertexAttrib4fv(index, v);
6587 break;
6588 }
6589 case SVGA3D_DECLTYPE_FLOAT2:
6590 {
6591 /* "Two-component float expanded to (float, float, 0, 1)." */
6592 GLfloat const *p = (GLfloat *)pv;
6593 GLfloat const v[4] = { p[0], p[1], 0.0f, 1.0f };
6594 pState->ext.glVertexAttrib4fv(index, v);
6595 break;
6596 }
6597 case SVGA3D_DECLTYPE_FLOAT3:
6598 {
6599 /* "Three-component float expanded to (float, float, float, 1)." */
6600 GLfloat const *p = (GLfloat *)pv;
6601 GLfloat const v[4] = { p[0], p[1], p[2], 1.0f };
6602 pState->ext.glVertexAttrib4fv(index, v);
6603 break;
6604 }
6605 case SVGA3D_DECLTYPE_FLOAT4:
6606 pState->ext.glVertexAttrib4fv(index, (GLfloat const *)pv);
6607 break;
6608 case SVGA3D_DECLTYPE_D3DCOLOR:
6609 /** @todo Need to swap bytes? */
6610 pState->ext.glVertexAttrib4Nubv(index, (GLubyte const *)pv);
6611 break;
6612 case SVGA3D_DECLTYPE_UBYTE4:
6613 pState->ext.glVertexAttrib4ubv(index, (GLubyte const *)pv);
6614 break;
6615 case SVGA3D_DECLTYPE_SHORT2:
6616 {
6617 /* "Two-component, signed short expanded to (value, value, 0, 1)." */
6618 GLshort const *p = (GLshort const *)pv;
6619 GLshort const v[4] = { p[0], p[1], 0, 1 };
6620 pState->ext.glVertexAttrib4sv(index, v);
6621 break;
6622 }
6623 case SVGA3D_DECLTYPE_SHORT4:
6624 pState->ext.glVertexAttrib4sv(index, (GLshort const *)pv);
6625 break;
6626 case SVGA3D_DECLTYPE_UBYTE4N:
6627 pState->ext.glVertexAttrib4Nubv(index, (GLubyte const *)pv);
6628 break;
6629 case SVGA3D_DECLTYPE_SHORT2N:
6630 {
6631 /* "Normalized, two-component, signed short, expanded to (first short/32767.0, second short/32767.0, 0, 1)." */
6632 GLshort const *p = (GLshort const *)pv;
6633 GLshort const v[4] = { p[0], p[1], 0, 1 };
6634 pState->ext.glVertexAttrib4Nsv(index, v);
6635 break;
6636 }
6637 case SVGA3D_DECLTYPE_SHORT4N:
6638 pState->ext.glVertexAttrib4Nsv(index, (GLshort const *)pv);
6639 break;
6640 case SVGA3D_DECLTYPE_USHORT2N:
6641 {
6642 GLushort const *p = (GLushort const *)pv;
6643 GLushort const v[4] = { p[0], p[1], 0, 1 };
6644 pState->ext.glVertexAttrib4Nusv(index, v);
6645 break;
6646 }
6647 case SVGA3D_DECLTYPE_USHORT4N:
6648 pState->ext.glVertexAttrib4Nusv(index, (GLushort const *)pv);
6649 break;
6650 case SVGA3D_DECLTYPE_UDEC3:
6651 {
6652 /** @todo Test */
6653 /* "Three-component, unsigned, 10 10 10 format expanded to (value, value, value, 1)." */
6654 uint32_t const u32 = *(uint32_t *)pv;
6655 GLfloat const v[4] = { (float)(u32 & 0x3ff), (float)((u32 >> 10) & 0x3ff), (float)((u32 >> 20) & 0x3ff), 1.0f };
6656 pState->ext.glVertexAttrib4fv(index, v);
6657 break;
6658 }
6659 case SVGA3D_DECLTYPE_DEC3N:
6660 {
6661 /** @todo Test */
6662 /* "Three-component, signed, 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)." */
6663 uint32_t const u32 = *(uint32_t *)pv;
6664 GLfloat const v[4] = { (float)(u32 & 0x3ff) / 511.0f, (float)((u32 >> 10) & 0x3ff) / 511.0f, (float)((u32 >> 20) & 0x3ff) / 511.0f, 1.0f };
6665 pState->ext.glVertexAttrib4fv(index, v);
6666 break;
6667 }
6668 case SVGA3D_DECLTYPE_FLOAT16_2:
6669 {
6670 /** @todo Test */
6671 /* "Two-component, 16-bit, floating point expanded to (value, value, 0, 1)." */
6672 uint16_t const *p = (uint16_t *)pv;
6673 GLfloat const v[4] = { vmsvga3dFloat16To32(p[0]), vmsvga3dFloat16To32(p[1]), 0.0f, 1.0f };
6674 pState->ext.glVertexAttrib4fv(index, v);
6675 break;
6676 }
6677 case SVGA3D_DECLTYPE_FLOAT16_4:
6678 {
6679 /** @todo Test */
6680 uint16_t const *p = (uint16_t *)pv;
6681 GLfloat const v[4] = { vmsvga3dFloat16To32(p[0]), vmsvga3dFloat16To32(p[1]),
6682 vmsvga3dFloat16To32(p[2]), vmsvga3dFloat16To32(p[3]) };
6683 pState->ext.glVertexAttrib4fv(index, v);
6684 break;
6685 }
6686 default:
6687 AssertFailedReturn(VERR_INVALID_PARAMETER);
6688 }
6689
6690 return VINF_SUCCESS;
6691}
6692
6693/* Convert VMWare primitive type to its OpenGL equivalent. */
6694/* Calculate the vertex count based on the primitive type and nr of primitives. */
6695static int vmsvga3dPrimitiveType2OGL(SVGA3dPrimitiveType PrimitiveType, GLenum *pMode, uint32_t cPrimitiveCount, uint32_t *pcVertices)
6696{
6697 switch (PrimitiveType)
6698 {
6699 case SVGA3D_PRIMITIVE_TRIANGLELIST:
6700 *pMode = GL_TRIANGLES;
6701 *pcVertices = cPrimitiveCount * 3;
6702 break;
6703 case SVGA3D_PRIMITIVE_POINTLIST:
6704 *pMode = GL_POINTS;
6705 *pcVertices = cPrimitiveCount;
6706 break;
6707 case SVGA3D_PRIMITIVE_LINELIST:
6708 *pMode = GL_LINES;
6709 *pcVertices = cPrimitiveCount * 2;
6710 break;
6711 case SVGA3D_PRIMITIVE_LINESTRIP:
6712 *pMode = GL_LINE_STRIP;
6713 *pcVertices = cPrimitiveCount + 1;
6714 break;
6715 case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
6716 *pMode = GL_TRIANGLE_STRIP;
6717 *pcVertices = cPrimitiveCount + 2;
6718 break;
6719 case SVGA3D_PRIMITIVE_TRIANGLEFAN:
6720 *pMode = GL_TRIANGLE_FAN;
6721 *pcVertices = cPrimitiveCount + 2;
6722 break;
6723 default:
6724 return VERR_INVALID_PARAMETER;
6725 }
6726 return VINF_SUCCESS;
6727}
6728
6729static int vmsvga3dResetTransformMatrices(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
6730{
6731 int rc;
6732
6733 /* Reset the view matrix (also takes the world matrix into account). */
6734 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].fValid == true)
6735 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_VIEW,
6736 pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix);
6737 else
6738 {
6739 float matrix[16];
6740
6741 /* identity matrix if no matrix set. */
6742 memset(matrix, 0, sizeof(matrix));
6743 matrix[0] = 1.0;
6744 matrix[5] = 1.0;
6745 matrix[10] = 1.0;
6746 matrix[15] = 1.0;
6747 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_VIEW, matrix);
6748 }
6749
6750 /* Reset the projection matrix. */
6751 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].fValid == true)
6752 {
6753 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_PROJECTION, pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].matrix);
6754 }
6755 else
6756 {
6757 float matrix[16];
6758
6759 /* identity matrix if no matrix set. */
6760 memset(matrix, 0, sizeof(matrix));
6761 matrix[0] = 1.0;
6762 matrix[5] = 1.0;
6763 matrix[10] = 1.0;
6764 matrix[15] = 1.0;
6765 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_PROJECTION, matrix);
6766 }
6767 AssertRC(rc);
6768 return rc;
6769}
6770
6771static int vmsvga3dDrawPrimitivesProcessVertexDecls(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext,
6772 uint32_t iVertexDeclBase, uint32_t numVertexDecls,
6773 SVGA3dVertexDecl *pVertexDecl,
6774 SVGA3dVertexDivisor const *paVertexDivisors)
6775{
6776 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6777 unsigned const sidVertex = pVertexDecl[0].array.surfaceId;
6778
6779 PVMSVGA3DSURFACE pVertexSurface;
6780 int rc = vmsvga3dSurfaceFromSid(pState, sidVertex, &pVertexSurface);
6781 AssertRCReturn(rc, rc);
6782
6783 Log(("vmsvga3dDrawPrimitives: vertex surface sid=%u\n", sidVertex));
6784
6785 /* Create and/or bind the vertex buffer. */
6786 if (pVertexSurface->oglId.buffer == OPENGL_INVALID_ID)
6787 {
6788 Log(("vmsvga3dDrawPrimitives: create vertex buffer fDirty=%d size=%x bytes\n", pVertexSurface->fDirty, pVertexSurface->paMipmapLevels[0].cbSurface));
6789 PVMSVGA3DCONTEXT pSavedCtx = pContext;
6790 pContext = &pState->SharedCtx;
6791 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6792
6793 pState->ext.glGenBuffers(1, &pVertexSurface->oglId.buffer);
6794 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6795 pVertexSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_BUFFER;
6796
6797 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pVertexSurface->oglId.buffer);
6798 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6799
6800 Assert(pVertexSurface->fDirty);
6801 /** @todo rethink usage dynamic/static */
6802 pState->ext.glBufferData(GL_ARRAY_BUFFER, pVertexSurface->paMipmapLevels[0].cbSurface, pVertexSurface->paMipmapLevels[0].pSurfaceData, GL_DYNAMIC_DRAW);
6803 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6804
6805 pVertexSurface->paMipmapLevels[0].fDirty = false;
6806 pVertexSurface->fDirty = false;
6807
6808 pVertexSurface->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
6809
6810 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, OPENGL_INVALID_ID);
6811 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6812
6813 pContext = pSavedCtx;
6814 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6815 }
6816
6817 Assert(pVertexSurface->fDirty == false);
6818 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pVertexSurface->oglId.buffer);
6819 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6820
6821 /* Setup the vertex declarations. */
6822 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
6823 {
6824 GLint size;
6825 GLenum type;
6826 GLboolean normalized;
6827 uint32_t cbAttrib;
6828 GLuint index = iVertexDeclBase + iVertex;
6829
6830 Log(("vmsvga3dDrawPrimitives: array index %d type=%s (%d) method=%s (%d) usage=%s (%d) usageIndex=%d stride=%d offset=%d\n", index, vmsvgaDeclType2String(pVertexDecl[iVertex].identity.type), pVertexDecl[iVertex].identity.type, vmsvgaDeclMethod2String(pVertexDecl[iVertex].identity.method), pVertexDecl[iVertex].identity.method, vmsvgaDeclUsage2String(pVertexDecl[iVertex].identity.usage), pVertexDecl[iVertex].identity.usage, pVertexDecl[iVertex].identity.usageIndex, pVertexDecl[iVertex].array.stride, pVertexDecl[iVertex].array.offset));
6831
6832 rc = vmsvga3dVertexDecl2OGL(pVertexDecl[iVertex].identity, size, type, normalized, cbAttrib);
6833 AssertRCReturn(rc, rc);
6834
6835 ASSERT_GUEST_RETURN( pVertexSurface->paMipmapLevels[0].cbSurface >= pVertexDecl[iVertex].array.offset
6836 && pVertexSurface->paMipmapLevels[0].cbSurface - pVertexDecl[iVertex].array.offset >= cbAttrib,
6837 VERR_INVALID_PARAMETER);
6838 RT_UNTRUSTED_VALIDATED_FENCE();
6839
6840 if (pContext->state.shidVertex != SVGA_ID_INVALID)
6841 {
6842 /* Use numbered vertex arrays (or attributes) when shaders are active. */
6843 if (pVertexDecl[iVertex].array.stride)
6844 {
6845 pState->ext.glEnableVertexAttribArray(index);
6846 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6847 pState->ext.glVertexAttribPointer(index, size, type, normalized, pVertexDecl[iVertex].array.stride,
6848 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6849 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6850
6851 GLuint divisor = paVertexDivisors && paVertexDivisors[index].instanceData ? 1 : 0;
6852 pState->ext.glVertexAttribDivisor(index, divisor);
6853 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6854
6855 /** @todo case SVGA3D_DECLUSAGE_COLOR: color component order not identical!! test GL_BGRA!! */
6856 }
6857 else
6858 {
6859 /*
6860 * D3D and OpenGL have a different meaning of value zero for the vertex array stride:
6861 * - D3D (VMSVGA): "use a zero stride to tell the runtime not to increment the vertex buffer offset."
6862 * - OpenGL: "If stride is 0, the generic vertex attributes are understood to be tightly packed in the array."
6863 * VMSVGA uses the D3D semantics.
6864 *
6865 * Use glVertexAttrib in order to tell OpenGL to reuse the zero stride attributes for each vertex.
6866 */
6867 pState->ext.glDisableVertexAttribArray(index);
6868 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6869
6870 const GLvoid *v = (uint8_t *)pVertexSurface->paMipmapLevels[0].pSurfaceData + pVertexDecl[iVertex].array.offset;
6871 vmsvga3dSetVertexAttrib(pState, index, &pVertexDecl[iVertex].identity, v);
6872 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6873 }
6874 }
6875 else
6876 {
6877 if (pVertexDecl[iVertex].array.stride == 0)
6878 {
6879 /* Zero stride means that the attribute pointer must not be increased.
6880 * See comment about stride in vmsvga3dDrawPrimitives.
6881 */
6882 LogRelMax(8, ("VMSVGA: Warning: zero stride array in fixed function pipeline\n"));
6883 AssertFailed();
6884 }
6885
6886 /* Use the predefined selection of vertex streams for the fixed pipeline. */
6887 switch (pVertexDecl[iVertex].identity.usage)
6888 {
6889 case SVGA3D_DECLUSAGE_POSITIONT:
6890 case SVGA3D_DECLUSAGE_POSITION:
6891 {
6892 glEnableClientState(GL_VERTEX_ARRAY);
6893 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6894 glVertexPointer(size, type, pVertexDecl[iVertex].array.stride,
6895 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6896 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6897 break;
6898 }
6899 case SVGA3D_DECLUSAGE_BLENDWEIGHT:
6900 AssertFailed();
6901 break;
6902 case SVGA3D_DECLUSAGE_BLENDINDICES:
6903 AssertFailed();
6904 break;
6905 case SVGA3D_DECLUSAGE_NORMAL:
6906 glEnableClientState(GL_NORMAL_ARRAY);
6907 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6908 glNormalPointer(type, pVertexDecl[iVertex].array.stride,
6909 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6910 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6911 break;
6912 case SVGA3D_DECLUSAGE_PSIZE:
6913 AssertFailed();
6914 break;
6915 case SVGA3D_DECLUSAGE_TEXCOORD:
6916 /* Specify the affected texture unit. */
6917#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x103
6918 glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
6919#else
6920 pState->ext.glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
6921#endif
6922 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
6923 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6924 glTexCoordPointer(size, type, pVertexDecl[iVertex].array.stride,
6925 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6926 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6927 break;
6928 case SVGA3D_DECLUSAGE_TANGENT:
6929 AssertFailed();
6930 break;
6931 case SVGA3D_DECLUSAGE_BINORMAL:
6932 AssertFailed();
6933 break;
6934 case SVGA3D_DECLUSAGE_TESSFACTOR:
6935 AssertFailed();
6936 break;
6937 case SVGA3D_DECLUSAGE_COLOR: /** @todo color component order not identical!! test GL_BGRA!! */
6938 glEnableClientState(GL_COLOR_ARRAY);
6939 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6940 glColorPointer(size, type, pVertexDecl[iVertex].array.stride,
6941 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6942 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6943 break;
6944 case SVGA3D_DECLUSAGE_FOG:
6945 glEnableClientState(GL_FOG_COORD_ARRAY);
6946 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6947 pState->ext.glFogCoordPointer(type, pVertexDecl[iVertex].array.stride,
6948 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6949 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6950 break;
6951 case SVGA3D_DECLUSAGE_DEPTH:
6952 AssertFailed();
6953 break;
6954 case SVGA3D_DECLUSAGE_SAMPLE:
6955 AssertFailed();
6956 break;
6957 case SVGA3D_DECLUSAGE_MAX: AssertFailed(); break; /* shut up gcc */
6958 }
6959 }
6960
6961#ifdef LOG_ENABLED
6962 if (pVertexDecl[iVertex].array.stride == 0)
6963 Log(("vmsvga3dDrawPrimitives: stride == 0! Can be valid\n"));
6964#endif
6965 }
6966
6967 return VINF_SUCCESS;
6968}
6969
6970static int vmsvga3dDrawPrimitivesCleanupVertexDecls(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t iVertexDeclBase,
6971 uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl)
6972{
6973 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6974
6975 /* Clean up the vertex declarations. */
6976 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
6977 {
6978 if (pVertexDecl[iVertex].identity.usage == SVGA3D_DECLUSAGE_POSITIONT)
6979 {
6980 /* Reset the transformation matrices in case of a switch back from pretransformed mode. */
6981 Log(("vmsvga3dDrawPrimitivesCleanupVertexDecls: reset world and projection matrices after transformation reset (pre-transformed -> transformed)\n"));
6982 vmsvga3dResetTransformMatrices(pThisCC, pContext);
6983 }
6984
6985 if (pContext->state.shidVertex != SVGA_ID_INVALID)
6986 {
6987 /* Use numbered vertex arrays when shaders are active. */
6988 pState->ext.glVertexAttribDivisor(iVertexDeclBase + iVertex, 0);
6989 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6990 pState->ext.glDisableVertexAttribArray(iVertexDeclBase + iVertex);
6991 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6992 }
6993 else
6994 {
6995 /* Use the predefined selection of vertex streams for the fixed pipeline. */
6996 switch (pVertexDecl[iVertex].identity.usage)
6997 {
6998 case SVGA3D_DECLUSAGE_POSITION:
6999 case SVGA3D_DECLUSAGE_POSITIONT:
7000 glDisableClientState(GL_VERTEX_ARRAY);
7001 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7002 break;
7003 case SVGA3D_DECLUSAGE_BLENDWEIGHT:
7004 break;
7005 case SVGA3D_DECLUSAGE_BLENDINDICES:
7006 break;
7007 case SVGA3D_DECLUSAGE_NORMAL:
7008 glDisableClientState(GL_NORMAL_ARRAY);
7009 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7010 break;
7011 case SVGA3D_DECLUSAGE_PSIZE:
7012 break;
7013 case SVGA3D_DECLUSAGE_TEXCOORD:
7014 /* Specify the affected texture unit. */
7015#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x103
7016 glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
7017#else
7018 pState->ext.glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
7019#endif
7020 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
7021 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7022 break;
7023 case SVGA3D_DECLUSAGE_TANGENT:
7024 break;
7025 case SVGA3D_DECLUSAGE_BINORMAL:
7026 break;
7027 case SVGA3D_DECLUSAGE_TESSFACTOR:
7028 break;
7029 case SVGA3D_DECLUSAGE_COLOR: /** @todo color component order not identical!! */
7030 glDisableClientState(GL_COLOR_ARRAY);
7031 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7032 break;
7033 case SVGA3D_DECLUSAGE_FOG:
7034 glDisableClientState(GL_FOG_COORD_ARRAY);
7035 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7036 break;
7037 case SVGA3D_DECLUSAGE_DEPTH:
7038 break;
7039 case SVGA3D_DECLUSAGE_SAMPLE:
7040 break;
7041 case SVGA3D_DECLUSAGE_MAX: AssertFailed(); break; /* shut up gcc */
7042 }
7043 }
7044 }
7045 /* Unbind the vertex buffer after usage. */
7046 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
7047 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7048 return VINF_SUCCESS;
7049}
7050
7051static DECLCALLBACK(int) vmsvga3dBackDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl,
7052 uint32_t numRanges, SVGA3dPrimitiveRange *pRange, uint32_t cVertexDivisor,
7053 SVGA3dVertexDivisor *pVertexDivisor)
7054{
7055 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7056 AssertReturn(pState, VERR_INTERNAL_ERROR);
7057 uint32_t iCurrentVertex;
7058
7059 Log(("vmsvga3dDrawPrimitives cid=%u numVertexDecls=%d numRanges=%d, cVertexDivisor=%d\n", cid, numVertexDecls, numRanges, cVertexDivisor));
7060
7061 /* Caller already check these, but it cannot hurt to check again... */
7062 AssertReturn(numVertexDecls && numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, VERR_INVALID_PARAMETER);
7063 AssertReturn(numRanges && numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, VERR_INVALID_PARAMETER);
7064 AssertReturn(!cVertexDivisor || cVertexDivisor == numVertexDecls, VERR_INVALID_PARAMETER);
7065
7066 if (!cVertexDivisor)
7067 pVertexDivisor = NULL; /* Be sure. */
7068
7069 PVMSVGA3DCONTEXT pContext;
7070 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7071 AssertRCReturn(rc, rc);
7072
7073 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7074
7075 /* Check for pretransformed vertex declarations. */
7076 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
7077 {
7078 switch (pVertexDecl[iVertex].identity.usage)
7079 {
7080 case SVGA3D_DECLUSAGE_POSITIONT:
7081 Log(("ShaderSetPositionTransformed: (%d,%d)\n", pContext->state.RectViewPort.w, pContext->state.RectViewPort.h));
7082 RT_FALL_THRU();
7083 case SVGA3D_DECLUSAGE_POSITION:
7084 ShaderSetPositionTransformed(pContext->pShaderContext, pContext->state.RectViewPort.w,
7085 pContext->state.RectViewPort.h,
7086 pVertexDecl[iVertex].identity.usage == SVGA3D_DECLUSAGE_POSITIONT);
7087 break;
7088 default: /* Shut up MSC. */ break;
7089 }
7090 }
7091
7092 /* Flush any shader changes; after (!) checking the vertex declarations to deal with pre-transformed vertices. */
7093 if (pContext->pShaderContext)
7094 {
7095 uint32_t rtHeight = 0;
7096
7097 if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA_ID_INVALID)
7098 {
7099 PVMSVGA3DSURFACE pRenderTarget;
7100 rc = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pRenderTarget);
7101 AssertRCReturn(rc, rc);
7102
7103 rtHeight = pRenderTarget->paMipmapLevels[0].mipmapSize.height;
7104 }
7105
7106 ShaderUpdateState(pContext->pShaderContext, rtHeight);
7107 }
7108
7109 /* Try to figure out if instancing is used.
7110 * Support simple instancing case with one set of indexed data and one set per-instance data.
7111 */
7112 uint32_t cInstances = 0;
7113 for (uint32_t iVertexDivisor = 0; iVertexDivisor < cVertexDivisor; ++iVertexDivisor)
7114 {
7115 if (pVertexDivisor[iVertexDivisor].indexedData)
7116 {
7117 if (cInstances == 0)
7118 cInstances = pVertexDivisor[iVertexDivisor].count;
7119 else
7120 Assert(cInstances == pVertexDivisor[iVertexDivisor].count);
7121 }
7122 else if (pVertexDivisor[iVertexDivisor].instanceData)
7123 {
7124 Assert(pVertexDivisor[iVertexDivisor].count == 1);
7125 }
7126 }
7127
7128 /* Process all vertex declarations. Each vertex buffer is represented by one stream. */
7129 iCurrentVertex = 0;
7130 while (iCurrentVertex < numVertexDecls)
7131 {
7132 uint32_t sidVertex = SVGA_ID_INVALID;
7133 uint32_t iVertex;
7134
7135 for (iVertex = iCurrentVertex; iVertex < numVertexDecls; iVertex++)
7136 {
7137 if ( sidVertex != SVGA_ID_INVALID
7138 && pVertexDecl[iVertex].array.surfaceId != sidVertex
7139 )
7140 break;
7141 sidVertex = pVertexDecl[iVertex].array.surfaceId;
7142 }
7143
7144 rc = vmsvga3dDrawPrimitivesProcessVertexDecls(pThisCC, pContext, iCurrentVertex, iVertex - iCurrentVertex,
7145 &pVertexDecl[iCurrentVertex], pVertexDivisor);
7146 AssertRCReturn(rc, rc);
7147
7148 iCurrentVertex = iVertex;
7149 }
7150
7151 /* Now draw the primitives. */
7152 for (unsigned iPrimitive = 0; iPrimitive < numRanges; iPrimitive++)
7153 {
7154 GLenum modeDraw;
7155 unsigned const sidIndex = pRange[iPrimitive].indexArray.surfaceId;
7156 PVMSVGA3DSURFACE pIndexSurface = NULL;
7157 unsigned cVertices;
7158
7159 Log(("Primitive %d: type %s\n", iPrimitive, vmsvga3dPrimitiveType2String(pRange[iPrimitive].primType)));
7160 rc = vmsvga3dPrimitiveType2OGL(pRange[iPrimitive].primType, &modeDraw, pRange[iPrimitive].primitiveCount, &cVertices);
7161 if (RT_FAILURE(rc))
7162 {
7163 AssertRC(rc);
7164 goto internal_error;
7165 }
7166
7167 if (sidIndex != SVGA3D_INVALID_ID)
7168 {
7169 AssertMsg(pRange[iPrimitive].indexWidth == sizeof(uint32_t) || pRange[iPrimitive].indexWidth == sizeof(uint16_t), ("Unsupported primitive width %d\n", pRange[iPrimitive].indexWidth));
7170
7171 rc = vmsvga3dSurfaceFromSid(pState, sidIndex, &pIndexSurface);
7172 if (RT_FAILURE(rc))
7173 {
7174 AssertRC(rc);
7175 goto internal_error;
7176 }
7177
7178 Log(("vmsvga3dDrawPrimitives: index surface sid=%u\n", sidIndex));
7179
7180 if (pIndexSurface->oglId.buffer == OPENGL_INVALID_ID)
7181 {
7182 Log(("vmsvga3dDrawPrimitives: create index buffer fDirty=%d size=%x bytes\n", pIndexSurface->fDirty, pIndexSurface->paMipmapLevels[0].cbSurface));
7183 pContext = &pState->SharedCtx;
7184 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7185
7186 pState->ext.glGenBuffers(1, &pIndexSurface->oglId.buffer);
7187 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7188 pIndexSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_BUFFER;
7189
7190 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->oglId.buffer);
7191 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7192
7193 Assert(pIndexSurface->fDirty);
7194
7195 /** @todo rethink usage dynamic/static */
7196 pState->ext.glBufferData(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->paMipmapLevels[0].cbSurface, pIndexSurface->paMipmapLevels[0].pSurfaceData, GL_DYNAMIC_DRAW);
7197 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7198
7199 pIndexSurface->paMipmapLevels[0].fDirty = false;
7200 pIndexSurface->fDirty = false;
7201
7202 pIndexSurface->f.s.surface1Flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
7203
7204 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OPENGL_INVALID_ID);
7205 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7206
7207 pContext = pState->papContexts[cid];
7208 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7209 }
7210 Assert(pIndexSurface->fDirty == false);
7211
7212 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->oglId.buffer);
7213 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7214 }
7215
7216 if (!pIndexSurface)
7217 {
7218 /* Render without an index buffer */
7219 Log(("DrawPrimitive %d cPrimitives=%d cVertices=%d index index bias=%d cInstances=%d\n", modeDraw, pRange[iPrimitive].primitiveCount, cVertices, pRange[iPrimitive].indexBias, cInstances));
7220 if (cInstances == 0)
7221 {
7222 glDrawArrays(modeDraw, pRange[iPrimitive].indexBias, cVertices);
7223 }
7224 else
7225 {
7226 pState->ext.glDrawArraysInstanced(modeDraw, pRange[iPrimitive].indexBias, cVertices, cInstances);
7227 }
7228 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7229 }
7230 else
7231 {
7232 Assert(pRange[iPrimitive].indexWidth == pRange[iPrimitive].indexArray.stride);
7233
7234 GLenum indexType;
7235 switch (pRange[iPrimitive].indexWidth)
7236 {
7237 case 1: indexType = GL_UNSIGNED_BYTE; break;
7238 case 2: indexType = GL_UNSIGNED_SHORT; break;
7239 default: AssertMsgFailed(("indexWidth %d\n", pRange[iPrimitive].indexWidth));
7240 RT_FALL_THROUGH();
7241 case 4: indexType = GL_UNSIGNED_INT; break;
7242 }
7243
7244 Log(("DrawIndexedPrimitive %d cPrimitives=%d cVertices=%d hint.first=%d hint.last=%d index offset=%d primitivecount=%d index width=%d index bias=%d cInstances=%d\n", modeDraw, pRange[iPrimitive].primitiveCount, cVertices, pVertexDecl[0].rangeHint.first, pVertexDecl[0].rangeHint.last, pRange[iPrimitive].indexArray.offset, pRange[iPrimitive].primitiveCount, pRange[iPrimitive].indexWidth, pRange[iPrimitive].indexBias, cInstances));
7245 if (cInstances == 0)
7246 {
7247 /* Render with an index buffer */
7248 if (pRange[iPrimitive].indexBias == 0)
7249 glDrawElements(modeDraw,
7250 cVertices,
7251 indexType,
7252 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset); /* byte offset in indices buffer */
7253 else
7254 pState->ext.glDrawElementsBaseVertex(modeDraw,
7255 cVertices,
7256 indexType,
7257 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */
7258 pRange[iPrimitive].indexBias); /* basevertex */
7259 }
7260 else
7261 {
7262 /* Render with an index buffer */
7263 if (pRange[iPrimitive].indexBias == 0)
7264 pState->ext.glDrawElementsInstanced(modeDraw,
7265 cVertices,
7266 indexType,
7267 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */
7268 cInstances);
7269 else
7270 pState->ext.glDrawElementsInstancedBaseVertex(modeDraw,
7271 cVertices,
7272 indexType,
7273 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */
7274 cInstances,
7275 pRange[iPrimitive].indexBias); /* basevertex */
7276 }
7277 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7278
7279 /* Unbind the index buffer after usage. */
7280 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7281 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7282 }
7283 }
7284
7285internal_error:
7286
7287 /* Deactivate the vertex declarations. */
7288 iCurrentVertex = 0;
7289 while (iCurrentVertex < numVertexDecls)
7290 {
7291 uint32_t sidVertex = SVGA_ID_INVALID;
7292 uint32_t iVertex;
7293
7294 for (iVertex = iCurrentVertex; iVertex < numVertexDecls; iVertex++)
7295 {
7296 if ( sidVertex != SVGA_ID_INVALID
7297 && pVertexDecl[iVertex].array.surfaceId != sidVertex
7298 )
7299 break;
7300 sidVertex = pVertexDecl[iVertex].array.surfaceId;
7301 }
7302
7303 rc = vmsvga3dDrawPrimitivesCleanupVertexDecls(pThisCC, pContext, iCurrentVertex,
7304 iVertex - iCurrentVertex, &pVertexDecl[iCurrentVertex]);
7305 AssertRCReturn(rc, rc);
7306
7307 iCurrentVertex = iVertex;
7308 }
7309
7310#ifdef DEBUG
7311 /* Check whether 'activeTexture' on texture unit 'i' matches what we expect. */
7312 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); ++i)
7313 {
7314 if (pContext->aSidActiveTextures[i] != SVGA3D_INVALID_ID)
7315 {
7316 PVMSVGA3DSURFACE pTexture;
7317 int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[i], &pTexture);
7318 AssertContinue(RT_SUCCESS(rc2));
7319
7320 GLint activeTextureUnit = 0;
7321 glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureUnit);
7322 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7323
7324 pState->ext.glActiveTexture(GL_TEXTURE0 + i);
7325 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7326
7327 GLint activeTexture = 0;
7328 glGetIntegerv(pTexture->bindingGL, &activeTexture);
7329 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7330
7331 pState->ext.glActiveTexture(activeTextureUnit);
7332 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7333
7334 AssertMsg(pTexture->oglId.texture == (GLuint)activeTexture,
7335 ("%d vs %d unit %d (active unit %d) sid=%u\n", pTexture->oglId.texture, activeTexture, i,
7336 activeTextureUnit - GL_TEXTURE0, pContext->aSidActiveTextures[i]));
7337 }
7338 }
7339#endif
7340
7341#if 0
7342 /* Dump render target to a bitmap. */
7343 if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA3D_INVALID_ID)
7344 {
7345 vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0]);
7346 PVMSVGA3DSURFACE pSurface;
7347 int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pSurface);
7348 if (RT_SUCCESS(rc2))
7349 vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpgl", "rt", "-post");
7350# if 0
7351 /* Stage 0 texture. */
7352 if (pContext->aSidActiveTextures[0] != SVGA3D_INVALID_ID)
7353 {
7354 vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->aSidActiveTextures[0]);
7355 rc2 = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[0], &pSurface);
7356 if (RT_SUCCESS(rc2))
7357 vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpgl", "rt", "-post-tx");
7358 }
7359# endif
7360 }
7361#endif
7362
7363 return rc;
7364}
7365
7366
7367static DECLCALLBACK(int) vmsvga3dBackShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData)
7368{
7369 PVMSVGA3DSHADER pShader;
7370 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7371 AssertReturn(pState, VERR_NO_MEMORY);
7372
7373 Log(("vmsvga3dShaderDefine cid=%u shid=%d type=%s cbData=0x%x\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cbData));
7374
7375 PVMSVGA3DCONTEXT pContext;
7376 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7377 AssertRCReturn(rc, rc);
7378
7379 AssertReturn(shid < SVGA3D_MAX_SHADER_IDS, VERR_INVALID_PARAMETER);
7380
7381 rc = vmsvga3dShaderParse(type, cbData, pShaderData);
7382 if (RT_FAILURE(rc))
7383 {
7384 AssertRC(rc);
7385 vmsvga3dShaderLogRel("Failed to parse", type, cbData, pShaderData);
7386 return rc;
7387 }
7388
7389 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7390
7391 if (type == SVGA3D_SHADERTYPE_VS)
7392 {
7393 if (shid >= pContext->cVertexShaders)
7394 {
7395 void *pvNew = RTMemRealloc(pContext->paVertexShader, sizeof(VMSVGA3DSHADER) * (shid + 1));
7396 AssertReturn(pvNew, VERR_NO_MEMORY);
7397 pContext->paVertexShader = (PVMSVGA3DSHADER)pvNew;
7398 memset(&pContext->paVertexShader[pContext->cVertexShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cVertexShaders));
7399 for (uint32_t i = pContext->cVertexShaders; i < shid + 1; i++)
7400 pContext->paVertexShader[i].id = SVGA3D_INVALID_ID;
7401 pContext->cVertexShaders = shid + 1;
7402 }
7403 /* If one already exists with this id, then destroy it now. */
7404 if (pContext->paVertexShader[shid].id != SVGA3D_INVALID_ID)
7405 vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paVertexShader[shid].type);
7406
7407 pShader = &pContext->paVertexShader[shid];
7408 }
7409 else
7410 {
7411 Assert(type == SVGA3D_SHADERTYPE_PS);
7412 if (shid >= pContext->cPixelShaders)
7413 {
7414 void *pvNew = RTMemRealloc(pContext->paPixelShader, sizeof(VMSVGA3DSHADER) * (shid + 1));
7415 AssertReturn(pvNew, VERR_NO_MEMORY);
7416 pContext->paPixelShader = (PVMSVGA3DSHADER)pvNew;
7417 memset(&pContext->paPixelShader[pContext->cPixelShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cPixelShaders));
7418 for (uint32_t i = pContext->cPixelShaders; i < shid + 1; i++)
7419 pContext->paPixelShader[i].id = SVGA3D_INVALID_ID;
7420 pContext->cPixelShaders = shid + 1;
7421 }
7422 /* If one already exists with this id, then destroy it now. */
7423 if (pContext->paPixelShader[shid].id != SVGA3D_INVALID_ID)
7424 vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paPixelShader[shid].type);
7425
7426 pShader = &pContext->paPixelShader[shid];
7427 }
7428
7429 memset(pShader, 0, sizeof(*pShader));
7430 pShader->id = shid;
7431 pShader->cid = cid;
7432 pShader->type = type;
7433 pShader->cbData = cbData;
7434 pShader->pShaderProgram = RTMemAllocZ(cbData);
7435 AssertReturn(pShader->pShaderProgram, VERR_NO_MEMORY);
7436 memcpy(pShader->pShaderProgram, pShaderData, cbData);
7437
7438#ifdef DUMP_SHADER_DISASSEMBLY
7439 LPD3DXBUFFER pDisassembly;
7440 HRESULT hr = D3DXDisassembleShader((const DWORD *)pShaderData, FALSE, NULL, &pDisassembly);
7441 if (hr == D3D_OK)
7442 {
7443 Log(("Shader disassembly:\n%s\n", pDisassembly->GetBufferPointer()));
7444 pDisassembly->Release();
7445 }
7446#endif
7447
7448 switch (type)
7449 {
7450 case SVGA3D_SHADERTYPE_VS:
7451 rc = ShaderCreateVertexShader(pContext->pShaderContext, (const uint32_t *)pShaderData, cbData, &pShader->u.pVertexShader);
7452 AssertRC(rc);
7453 break;
7454
7455 case SVGA3D_SHADERTYPE_PS:
7456 rc = ShaderCreatePixelShader(pContext->pShaderContext, (const uint32_t *)pShaderData, cbData, &pShader->u.pPixelShader);
7457 AssertRC(rc);
7458 break;
7459
7460 default:
7461 AssertFailedReturn(VERR_INVALID_PARAMETER);
7462 }
7463 if (rc != VINF_SUCCESS)
7464 {
7465 vmsvga3dShaderLogRel("Failed to create", type, cbData, pShaderData);
7466
7467 RTMemFree(pShader->pShaderProgram);
7468 memset(pShader, 0, sizeof(*pShader));
7469 pShader->id = SVGA3D_INVALID_ID;
7470 }
7471
7472 return rc;
7473}
7474
7475static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type)
7476{
7477 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7478 AssertReturn(pState, VERR_NO_MEMORY);
7479 PVMSVGA3DSHADER pShader = NULL;
7480
7481 Log(("vmsvga3dShaderDestroy cid=%u shid=%d type=%s\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL"));
7482
7483 PVMSVGA3DCONTEXT pContext;
7484 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7485 AssertRCReturn(rc, rc);
7486
7487 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7488
7489 if (type == SVGA3D_SHADERTYPE_VS)
7490 {
7491 if ( shid < pContext->cVertexShaders
7492 && pContext->paVertexShader[shid].id == shid)
7493 {
7494 pShader = &pContext->paVertexShader[shid];
7495 if (pContext->state.shidVertex == shid)
7496 {
7497 rc = ShaderSetVertexShader(pContext->pShaderContext, NULL);
7498 AssertRC(rc);
7499 }
7500
7501 rc = ShaderDestroyVertexShader(pContext->pShaderContext, pShader->u.pVertexShader);
7502 AssertRC(rc);
7503 }
7504 }
7505 else
7506 {
7507 Assert(type == SVGA3D_SHADERTYPE_PS);
7508 if ( shid < pContext->cPixelShaders
7509 && pContext->paPixelShader[shid].id == shid)
7510 {
7511 pShader = &pContext->paPixelShader[shid];
7512 if (pContext->state.shidPixel == shid)
7513 {
7514 ShaderSetPixelShader(pContext->pShaderContext, NULL);
7515 AssertRC(rc);
7516 }
7517
7518 rc = ShaderDestroyPixelShader(pContext->pShaderContext, pShader->u.pPixelShader);
7519 AssertRC(rc);
7520 }
7521 }
7522
7523 if (pShader)
7524 {
7525 if (pShader->pShaderProgram)
7526 RTMemFree(pShader->pShaderProgram);
7527 memset(pShader, 0, sizeof(*pShader));
7528 pShader->id = SVGA3D_INVALID_ID;
7529 }
7530 else
7531 AssertFailedReturn(VERR_INVALID_PARAMETER);
7532
7533 return VINF_SUCCESS;
7534}
7535
7536static DECLCALLBACK(int) vmsvga3dBackShaderSet(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid)
7537{
7538 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7539 AssertReturn(pState, VERR_NO_MEMORY);
7540 int rc;
7541
7542 Log(("vmsvga3dShaderSet cid=%u type=%s shid=%d\n", cid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", shid));
7543
7544 if (!pContext)
7545 {
7546 rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7547 AssertRCReturn(rc, rc);
7548 }
7549
7550 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7551
7552 if (type == SVGA3D_SHADERTYPE_VS)
7553 {
7554 /* Save for vm state save/restore. */
7555 pContext->state.shidVertex = shid;
7556 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VERTEXSHADER;
7557
7558 if ( shid < pContext->cVertexShaders
7559 && pContext->paVertexShader[shid].id == shid)
7560 {
7561 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[shid];
7562 Assert(type == pShader->type);
7563
7564 rc = ShaderSetVertexShader(pContext->pShaderContext, pShader->u.pVertexShader);
7565 AssertRCReturn(rc, rc);
7566 }
7567 else
7568 if (shid == SVGA_ID_INVALID)
7569 {
7570 /* Unselect shader. */
7571 rc = ShaderSetVertexShader(pContext->pShaderContext, NULL);
7572 AssertRCReturn(rc, rc);
7573 }
7574 else
7575 AssertFailedReturn(VERR_INVALID_PARAMETER);
7576 }
7577 else
7578 {
7579 /* Save for vm state save/restore. */
7580 pContext->state.shidPixel = shid;
7581 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_PIXELSHADER;
7582
7583 Assert(type == SVGA3D_SHADERTYPE_PS);
7584 if ( shid < pContext->cPixelShaders
7585 && pContext->paPixelShader[shid].id == shid)
7586 {
7587 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[shid];
7588 Assert(type == pShader->type);
7589
7590 rc = ShaderSetPixelShader(pContext->pShaderContext, pShader->u.pPixelShader);
7591 AssertRCReturn(rc, rc);
7592 }
7593 else
7594 if (shid == SVGA_ID_INVALID)
7595 {
7596 /* Unselect shader. */
7597 rc = ShaderSetPixelShader(pContext->pShaderContext, NULL);
7598 AssertRCReturn(rc, rc);
7599 }
7600 else
7601 AssertFailedReturn(VERR_INVALID_PARAMETER);
7602 }
7603
7604 return VINF_SUCCESS;
7605}
7606
7607static DECLCALLBACK(int) vmsvga3dBackShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues)
7608{
7609 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7610 AssertReturn(pState, VERR_NO_MEMORY);
7611
7612 Log(("vmsvga3dShaderSetConst cid=%u reg=%x type=%s cregs=%d ctype=%x\n", cid, reg, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cRegisters, ctype));
7613
7614 PVMSVGA3DCONTEXT pContext;
7615 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7616 AssertRCReturn(rc, rc);
7617
7618 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7619
7620 for (uint32_t i = 0; i < cRegisters; i++)
7621 {
7622#ifdef LOG_ENABLED
7623 switch (ctype)
7624 {
7625 case SVGA3D_CONST_TYPE_FLOAT:
7626 {
7627 float *pValuesF = (float *)pValues;
7628 Log(("ConstantF %d: value=" FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "\n",
7629 reg + i, FLOAT_FMT_ARGS(pValuesF[i*4 + 0]), FLOAT_FMT_ARGS(pValuesF[i*4 + 1]), FLOAT_FMT_ARGS(pValuesF[i*4 + 2]), FLOAT_FMT_ARGS(pValuesF[i*4 + 3])));
7630 break;
7631 }
7632
7633 case SVGA3D_CONST_TYPE_INT:
7634 Log(("ConstantI %d: value=%d, %d, %d, %d\n", reg + i, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]));
7635 break;
7636
7637 case SVGA3D_CONST_TYPE_BOOL:
7638 Log(("ConstantB %d: value=%d, %d, %d, %d\n", reg + i, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]));
7639 break;
7640
7641 default:
7642 AssertFailedReturn(VERR_INVALID_PARAMETER);
7643 }
7644#endif
7645 vmsvga3dSaveShaderConst(pContext, reg + i, type, ctype, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]);
7646 }
7647
7648 switch (type)
7649 {
7650 case SVGA3D_SHADERTYPE_VS:
7651 switch (ctype)
7652 {
7653 case SVGA3D_CONST_TYPE_FLOAT:
7654 rc = ShaderSetVertexShaderConstantF(pContext->pShaderContext, reg, (const float *)pValues, cRegisters);
7655 break;
7656
7657 case SVGA3D_CONST_TYPE_INT:
7658 rc = ShaderSetVertexShaderConstantI(pContext->pShaderContext, reg, (const int32_t *)pValues, cRegisters);
7659 break;
7660
7661 case SVGA3D_CONST_TYPE_BOOL:
7662 rc = ShaderSetVertexShaderConstantB(pContext->pShaderContext, reg, (const uint8_t *)pValues, cRegisters);
7663 break;
7664
7665 default:
7666 AssertFailedReturn(VERR_INVALID_PARAMETER);
7667 }
7668 AssertRCReturn(rc, rc);
7669 break;
7670
7671 case SVGA3D_SHADERTYPE_PS:
7672 switch (ctype)
7673 {
7674 case SVGA3D_CONST_TYPE_FLOAT:
7675 rc = ShaderSetPixelShaderConstantF(pContext->pShaderContext, reg, (const float *)pValues, cRegisters);
7676 break;
7677
7678 case SVGA3D_CONST_TYPE_INT:
7679 rc = ShaderSetPixelShaderConstantI(pContext->pShaderContext, reg, (const int32_t *)pValues, cRegisters);
7680 break;
7681
7682 case SVGA3D_CONST_TYPE_BOOL:
7683 rc = ShaderSetPixelShaderConstantB(pContext->pShaderContext, reg, (const uint8_t *)pValues, cRegisters);
7684 break;
7685
7686 default:
7687 AssertFailedReturn(VERR_INVALID_PARAMETER);
7688 }
7689 AssertRCReturn(rc, rc);
7690 break;
7691
7692 default:
7693 AssertFailedReturn(VERR_INVALID_PARAMETER);
7694 }
7695
7696 return VINF_SUCCESS;
7697}
7698
7699static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryCreate(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7700{
7701 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7702 AssertReturn(pState->ext.glGenQueries, VERR_NOT_SUPPORTED);
7703 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7704
7705 GLuint idQuery = 0;
7706 pState->ext.glGenQueries(1, &idQuery);
7707 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7708 AssertReturn(idQuery, VERR_INTERNAL_ERROR);
7709 pContext->occlusion.idQuery = idQuery;
7710 return VINF_SUCCESS;
7711}
7712
7713static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7714{
7715 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7716 AssertReturn(pState->ext.glDeleteQueries, VERR_NOT_SUPPORTED);
7717 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7718
7719 if (pContext->occlusion.idQuery)
7720 {
7721 pState->ext.glDeleteQueries(1, &pContext->occlusion.idQuery);
7722 }
7723 return VINF_SUCCESS;
7724}
7725
7726static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryBegin(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7727{
7728 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7729 AssertReturn(pState->ext.glBeginQuery, VERR_NOT_SUPPORTED);
7730 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7731
7732 pState->ext.glBeginQuery(GL_ANY_SAMPLES_PASSED, pContext->occlusion.idQuery);
7733 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7734 return VINF_SUCCESS;
7735}
7736
7737static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryEnd(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7738{
7739 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7740 AssertReturn(pState->ext.glEndQuery, VERR_NOT_SUPPORTED);
7741 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7742
7743 pState->ext.glEndQuery(GL_ANY_SAMPLES_PASSED);
7744 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7745 return VINF_SUCCESS;
7746}
7747
7748static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryGetData(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t *pu32Pixels)
7749{
7750 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7751 AssertReturn(pState->ext.glGetQueryObjectuiv, VERR_NOT_SUPPORTED);
7752 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7753
7754 GLuint pixels = 0;
7755 pState->ext.glGetQueryObjectuiv(pContext->occlusion.idQuery, GL_QUERY_RESULT, &pixels);
7756 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7757
7758 *pu32Pixels = (uint32_t)pixels;
7759 return VINF_SUCCESS;
7760}
7761
7762/**
7763 * Worker for vmsvga3dUpdateHeapBuffersForSurfaces.
7764 *
7765 * This will allocate heap buffers if necessary, thus increasing the memory
7766 * usage of the process.
7767 *
7768 * @todo Would be interesting to share this code with the saved state code.
7769 *
7770 * @returns VBox status code.
7771 * @param pThisCC The VGA/VMSVGA context.
7772 * @param pSurface The surface to refresh the heap buffers for.
7773 */
7774static DECLCALLBACK(int) vmsvga3dBackSurfaceUpdateHeapBuffers(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface)
7775{
7776 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7777 AssertReturn(pState, VERR_INVALID_STATE);
7778
7779 /*
7780 * Currently we've got trouble retreving bit for DEPTHSTENCIL
7781 * surfaces both for OpenGL and D3D, so skip these here (don't
7782 * wast memory on them).
7783 */
7784 uint32_t const fSwitchFlags = pSurface->f.s.surface1Flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK;
7785 if ( fSwitchFlags != SVGA3D_SURFACE_HINT_DEPTHSTENCIL
7786 && fSwitchFlags != (SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE))
7787 {
7788 /*
7789 * Change OpenGL context to the one the surface is associated with.
7790 */
7791 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
7792 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7793
7794 /*
7795 * Work thru each mipmap level for each face.
7796 */
7797 for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++)
7798 {
7799 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[iFace * pSurface->cLevels];
7800 for (uint32_t i = 0; i < pSurface->cLevels; i++, pMipmapLevel++)
7801 {
7802 if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
7803 {
7804 Assert(pMipmapLevel->cbSurface);
7805 Assert(pMipmapLevel->cbSurface == pMipmapLevel->cbSurfacePlane * pMipmapLevel->mipmapSize.depth);
7806
7807 /*
7808 * Make sure we've got surface memory buffer.
7809 */
7810 uint8_t *pbDst = (uint8_t *)pMipmapLevel->pSurfaceData;
7811 if (!pbDst)
7812 {
7813 pMipmapLevel->pSurfaceData = pbDst = (uint8_t *)RTMemAllocZ(pMipmapLevel->cbSurface);
7814 AssertReturn(pbDst, VERR_NO_MEMORY);
7815 }
7816
7817 /*
7818 * OpenGL specifics.
7819 */
7820 switch (pSurface->enmOGLResType)
7821 {
7822 case VMSVGA3D_OGLRESTYPE_TEXTURE:
7823 {
7824 GLint activeTexture;
7825 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
7826 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7827
7828 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
7829 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7830
7831 /* Set row length and alignment of the output data. */
7832 VMSVGAPACKPARAMS SavedParams;
7833 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
7834
7835 glGetTexImage(GL_TEXTURE_2D,
7836 i,
7837 pSurface->formatGL,
7838 pSurface->typeGL,
7839 pbDst);
7840 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7841
7842 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
7843
7844 /* Restore the old active texture. */
7845 glBindTexture(GL_TEXTURE_2D, activeTexture);
7846 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7847 break;
7848 }
7849
7850 case VMSVGA3D_OGLRESTYPE_BUFFER:
7851 {
7852 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
7853 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7854
7855 void *pvSrc = pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
7856 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7857 if (RT_VALID_PTR(pvSrc))
7858 memcpy(pbDst, pvSrc, pMipmapLevel->cbSurface);
7859 else
7860 AssertPtr(pvSrc);
7861
7862 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
7863 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7864
7865 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
7866 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7867 break;
7868 }
7869
7870 default:
7871 AssertMsgFailed(("%#x\n", fSwitchFlags));
7872 }
7873 }
7874 /* else: There is no data in hardware yet, so whatever we got is already current. */
7875 }
7876 }
7877 }
7878
7879 return VINF_SUCCESS;
7880}
7881
7882static DECLCALLBACK(int) vmsvga3dBackQueryInterface(PVGASTATECC pThisCC, char const *pszInterfaceName, void *pvInterfaceFuncs, size_t cbInterfaceFuncs)
7883{
7884 RT_NOREF(pThisCC);
7885
7886 int rc = VINF_SUCCESS;
7887 if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_3D) == 0)
7888 {
7889 if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCS3D))
7890 {
7891 if (pvInterfaceFuncs)
7892 {
7893 VMSVGA3DBACKENDFUNCS3D *p = (VMSVGA3DBACKENDFUNCS3D *)pvInterfaceFuncs;
7894 p->pfnInit = vmsvga3dBackInit;
7895 p->pfnPowerOn = vmsvga3dBackPowerOn;
7896 p->pfnTerminate = vmsvga3dBackTerminate;
7897 p->pfnReset = vmsvga3dBackReset;
7898 p->pfnQueryCaps = vmsvga3dBackQueryCaps;
7899 p->pfnChangeMode = vmsvga3dBackChangeMode;
7900 p->pfnCreateTexture = vmsvga3dBackCreateTexture;
7901 p->pfnSurfaceDestroy = vmsvga3dBackSurfaceDestroy;
7902 p->pfnSurfaceInvalidateImage = vmsvga3dBackSurfaceInvalidateImage;
7903 p->pfnSurfaceCopy = vmsvga3dBackSurfaceCopy;
7904 p->pfnSurfaceDMACopyBox = vmsvga3dBackSurfaceDMACopyBox;
7905 p->pfnSurfaceStretchBlt = vmsvga3dBackSurfaceStretchBlt;
7906 p->pfnUpdateHostScreenViewport = vmsvga3dBackUpdateHostScreenViewport;
7907 p->pfnDefineScreen = vmsvga3dBackDefineScreen;
7908 p->pfnDestroyScreen = vmsvga3dBackDestroyScreen;
7909 p->pfnSurfaceBlitToScreen = vmsvga3dBackSurfaceBlitToScreen;
7910 p->pfnSurfaceUpdateHeapBuffers = vmsvga3dBackSurfaceUpdateHeapBuffers;
7911 }
7912 }
7913 else
7914 {
7915 AssertFailed();
7916 rc = VERR_INVALID_PARAMETER;
7917 }
7918 }
7919 else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_VGPU9) == 0)
7920 {
7921 if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSVGPU9))
7922 {
7923 if (pvInterfaceFuncs)
7924 {
7925 VMSVGA3DBACKENDFUNCSVGPU9 *p = (VMSVGA3DBACKENDFUNCSVGPU9 *)pvInterfaceFuncs;
7926 p->pfnContextDefine = vmsvga3dBackContextDefine;
7927 p->pfnContextDestroy = vmsvga3dBackContextDestroy;
7928 p->pfnSetTransform = vmsvga3dBackSetTransform;
7929 p->pfnSetZRange = vmsvga3dBackSetZRange;
7930 p->pfnSetRenderState = vmsvga3dBackSetRenderState;
7931 p->pfnSetRenderTarget = vmsvga3dBackSetRenderTarget;
7932 p->pfnSetTextureState = vmsvga3dBackSetTextureState;
7933 p->pfnSetMaterial = vmsvga3dBackSetMaterial;
7934 p->pfnSetLightData = vmsvga3dBackSetLightData;
7935 p->pfnSetLightEnabled = vmsvga3dBackSetLightEnabled;
7936 p->pfnSetViewPort = vmsvga3dBackSetViewPort;
7937 p->pfnSetClipPlane = vmsvga3dBackSetClipPlane;
7938 p->pfnCommandClear = vmsvga3dBackCommandClear;
7939 p->pfnDrawPrimitives = vmsvga3dBackDrawPrimitives;
7940 p->pfnSetScissorRect = vmsvga3dBackSetScissorRect;
7941 p->pfnGenerateMipmaps = vmsvga3dBackGenerateMipmaps;
7942 p->pfnShaderDefine = vmsvga3dBackShaderDefine;
7943 p->pfnShaderDestroy = vmsvga3dBackShaderDestroy;
7944 p->pfnShaderSet = vmsvga3dBackShaderSet;
7945 p->pfnShaderSetConst = vmsvga3dBackShaderSetConst;
7946 p->pfnOcclusionQueryCreate = vmsvga3dBackOcclusionQueryCreate;
7947 p->pfnOcclusionQueryDelete = vmsvga3dBackOcclusionQueryDelete;
7948 p->pfnOcclusionQueryBegin = vmsvga3dBackOcclusionQueryBegin;
7949 p->pfnOcclusionQueryEnd = vmsvga3dBackOcclusionQueryEnd;
7950 p->pfnOcclusionQueryGetData = vmsvga3dBackOcclusionQueryGetData;
7951 }
7952 }
7953 else
7954 {
7955 AssertFailed();
7956 rc = VERR_INVALID_PARAMETER;
7957 }
7958 }
7959 else
7960 rc = VERR_NOT_IMPLEMENTED;
7961 return rc;
7962}
7963
7964
7965extern VMSVGA3DBACKENDDESC const g_BackendLegacy =
7966{
7967 "LEGACY",
7968 vmsvga3dBackQueryInterface
7969};
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use