VirtualBox

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

Last change on this file since 90778 was 89163, checked in by vboxsync, 3 years ago

Devices/Graphics: Build new and old 3D backend. bugref:9830

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 309.2 KB
Line 
1/* $Id: DevVGA-SVGA3d-ogl.cpp 89163 2021-05-19 13:12:44Z vboxsync $ */
2/** @file
3 * DevVMWare - VMWare SVGA device
4 */
5
6/*
7 * Copyright (C) 2013-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22/* Enable to disassemble defined shaders. (Windows host only) */
23#if defined(RT_OS_WINDOWS) && defined(DEBUG) && 0 /* Disabled as we don't have the DirectX SDK avaible atm. */
24# define DUMP_SHADER_DISASSEMBLY
25#endif
26#ifdef DEBUG_bird
27//# define RTMEM_WRAP_TO_EF_APIS
28#endif
29#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
30#include <VBox/vmm/pdmdev.h>
31#include <VBox/version.h>
32#include <VBox/err.h>
33#include <VBox/log.h>
34#include <VBox/vmm/pgm.h>
35#include <VBox/AssertGuest.h>
36
37#include <iprt/assert.h>
38#include <iprt/semaphore.h>
39#include <iprt/uuid.h>
40#include <iprt/mem.h>
41
42#include <VBoxVideo.h> /* required by DevVGA.h */
43#include <VBoxVideo3D.h>
44
45/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
46#include "DevVGA.h"
47
48#include "DevVGA-SVGA.h"
49#include "DevVGA-SVGA3d.h"
50#include "DevVGA-SVGA3d-internal.h"
51
52#ifdef DUMP_SHADER_DISASSEMBLY
53# include <d3dx9shader.h>
54#endif
55
56#include <stdlib.h>
57#include <math.h>
58#include <float.h> /* FLT_MIN */
59
60
61/*********************************************************************************************************************************
62* Defined Constants And Macros *
63*********************************************************************************************************************************/
64#ifndef VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE
65# define VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE 1.0
66#endif
67
68#ifdef VMSVGA3D_DYNAMIC_LOAD
69# define OGLGETPROCADDRESS glLdrGetProcAddress
70#else
71#ifdef RT_OS_WINDOWS
72# define OGLGETPROCADDRESS MyWinGetProcAddress
73DECLINLINE(PROC) MyWinGetProcAddress(const char *pszSymbol)
74{
75 /* Khronos: [on failure] "some implementations will return other values. 1, 2, and 3 are used, as well as -1". */
76 PROC p = wglGetProcAddress(pszSymbol);
77 if (RT_VALID_PTR(p))
78 return p;
79 return 0;
80}
81#elif defined(RT_OS_DARWIN)
82# include <dlfcn.h>
83# define OGLGETPROCADDRESS MyNSGLGetProcAddress
84/** Resolves an OpenGL symbol. */
85static void *MyNSGLGetProcAddress(const char *pszSymbol)
86{
87 /* Another copy in shaderapi.c. */
88 static void *s_pvImage = NULL;
89 if (s_pvImage == NULL)
90 s_pvImage = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
91 return s_pvImage ? dlsym(s_pvImage, pszSymbol) : NULL;
92}
93
94#else
95# define OGLGETPROCADDRESS(x) glXGetProcAddress((const GLubyte *)x)
96#endif
97#endif
98
99/* Invert y-coordinate for OpenGL's bottom left origin. */
100#define D3D_TO_OGL_Y_COORD(ptrSurface, y_coordinate) (ptrSurface->paMipmapLevels[0].mipmapSize.height - (y_coordinate))
101#define D3D_TO_OGL_Y_COORD_MIPLEVEL(ptrMipLevel, y_coordinate) (ptrMipLevel->size.height - (y_coordinate))
102
103/**
104 * Macro for doing something and then checking for errors during initialization.
105 * Uses AssertLogRelMsg.
106 */
107#define VMSVGA3D_INIT_CHECKED(a_Expr) \
108 do \
109 { \
110 a_Expr; \
111 GLenum iGlError = glGetError(); \
112 AssertLogRelMsg(iGlError == GL_NO_ERROR, ("VMSVGA3d: %s -> %#x\n", #a_Expr, iGlError)); \
113 } while (0)
114
115/**
116 * Macro for doing something and then checking for errors during initialization,
117 * doing the same in the other context when enabled.
118 *
119 * This will try both profiles in dual profile builds. Caller must be in the
120 * default context.
121 *
122 * Uses AssertLogRelMsg to indicate trouble.
123 */
124#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
125# define VMSVGA3D_INIT_CHECKED_BOTH(a_pState, a_pContext, a_pOtherCtx, a_Expr) \
126 do \
127 { \
128 for (uint32_t i = 0; i < 64; i++) if (glGetError() == GL_NO_ERROR) break; Assert(glGetError() == GL_NO_ERROR); \
129 a_Expr; \
130 GLenum iGlError = glGetError(); \
131 if (iGlError != GL_NO_ERROR) \
132 { \
133 VMSVGA3D_SET_CURRENT_CONTEXT(a_pState, a_pOtherCtx); \
134 for (uint32_t i = 0; i < 64; i++) if (glGetError() == GL_NO_ERROR) break; Assert(glGetError() == GL_NO_ERROR); \
135 a_Expr; \
136 GLenum iGlError2 = glGetError(); \
137 AssertLogRelMsg(iGlError2 == GL_NO_ERROR, ("VMSVGA3d: %s -> %#x / %#x\n", #a_Expr, iGlError, iGlError2)); \
138 VMSVGA3D_SET_CURRENT_CONTEXT(a_pState, a_pContext); \
139 } \
140 } while (0)
141#else
142# define VMSVGA3D_INIT_CHECKED_BOTH(a_pState, a_pContext, a_pOtherCtx, a_Expr) VMSVGA3D_INIT_CHECKED(a_Expr)
143#endif
144
145
146/*********************************************************************************************************************************
147* Global Variables *
148*********************************************************************************************************************************/
149/* Define the default light parameters as specified by MSDN. */
150/** @todo move out; fetched from Wine */
151const SVGA3dLightData vmsvga3d_default_light =
152{
153 SVGA3D_LIGHTTYPE_DIRECTIONAL, /* type */
154 false, /* inWorldSpace */
155 { 1.0f, 1.0f, 1.0f, 0.0f }, /* diffuse r,g,b,a */
156 { 0.0f, 0.0f, 0.0f, 0.0f }, /* specular r,g,b,a */
157 { 0.0f, 0.0f, 0.0f, 0.0f }, /* ambient r,g,b,a, */
158 { 0.0f, 0.0f, 0.0f }, /* position x,y,z */
159 { 0.0f, 0.0f, 1.0f }, /* direction x,y,z */
160 0.0f, /* range */
161 0.0f, /* falloff */
162 0.0f, 0.0f, 0.0f, /* attenuation 0,1,2 */
163 0.0f, /* theta */
164 0.0f /* phi */
165};
166
167
168/*********************************************************************************************************************************
169* Internal Functions *
170*********************************************************************************************************************************/
171static int vmsvga3dContextDestroyOgl(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid);
172static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid);
173static void vmsvgaColor2GLFloatArray(uint32_t color, GLfloat *pRed, GLfloat *pGreen, GLfloat *pBlue, GLfloat *pAlpha);
174static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData);
175static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4]);
176static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type);
177static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext);
178static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext, PVMSVGA3DSURFACE pSurface);
179
180/* Generated by VBoxDef2LazyLoad from the VBoxSVGA3D.def and VBoxSVGA3DObjC.def files. */
181extern "C" int ExplicitlyLoadVBoxSVGA3D(bool fResolveAllImports, PRTERRINFO pErrInfo);
182
183
184/**
185 * Checks if the given OpenGL extension is supported.
186 *
187 * @returns true if supported, false if not.
188 * @param pState The VMSVGA3d state.
189 * @param rsMinGLVersion The OpenGL version that introduced this feature
190 * into the core.
191 * @param pszWantedExtension The name of the OpenGL extension we want padded
192 * with one space at each end.
193 * @remarks Init time only.
194 */
195static bool vmsvga3dCheckGLExtension(PVMSVGA3DSTATE pState, float rsMinGLVersion, const char *pszWantedExtension)
196{
197 RT_NOREF(rsMinGLVersion);
198 /* check padding. */
199 Assert(pszWantedExtension[0] == ' ');
200 Assert(pszWantedExtension[1] != ' ');
201 Assert(strchr(&pszWantedExtension[1], ' ') + 1 == strchr(pszWantedExtension, '\0'));
202
203 /* Look it up. */
204 bool fRet = false;
205 if (strstr(pState->pszExtensions, pszWantedExtension))
206 fRet = true;
207
208 /* Temporarily. Later start if (rsMinGLVersion != 0.0 && fActualGLVersion >= rsMinGLVersion) return true; */
209#ifdef RT_OS_DARWIN
210 AssertMsg( rsMinGLVersion == 0.0
211 || fRet == (pState->rsGLVersion >= rsMinGLVersion)
212 || VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE == 2.1,
213 ("%s actual:%d min:%d fRet=%d\n",
214 pszWantedExtension, (int)(pState->rsGLVersion * 10), (int)(rsMinGLVersion * 10), fRet));
215#else
216 AssertMsg(rsMinGLVersion == 0.0 || fRet == (pState->rsGLVersion >= rsMinGLVersion),
217 ("%s actual:%d min:%d fRet=%d\n",
218 pszWantedExtension, (int)(pState->rsGLVersion * 10), (int)(rsMinGLVersion * 10), fRet));
219#endif
220 return fRet;
221}
222
223
224/**
225 * Outputs GL_EXTENSIONS list to the release log.
226 */
227static void vmsvga3dLogRelExtensions(const char *pszPrefix, const char *pszExtensions)
228{
229 /* OpenGL 3.0 interface (glGetString(GL_EXTENSIONS) return NULL). */
230 bool fBuffered = RTLogRelSetBuffering(true);
231
232 /*
233 * Determin the column widths first.
234 */
235 size_t acchWidths[4] = { 1, 1, 1, 1 };
236 uint32_t i;
237 const char *psz = pszExtensions;
238 for (i = 0; ; i++)
239 {
240 while (*psz == ' ')
241 psz++;
242 if (!*psz)
243 break;
244
245 const char *pszEnd = strchr(psz, ' ');
246 AssertBreak(pszEnd);
247 size_t cch = pszEnd - psz;
248
249 uint32_t iColumn = i % RT_ELEMENTS(acchWidths);
250 if (acchWidths[iColumn] < cch)
251 acchWidths[iColumn] = cch;
252
253 psz = pszEnd;
254 }
255
256 /*
257 * Output it.
258 */
259 LogRel(("VMSVGA3d: %sOpenGL extensions (%d):", pszPrefix, i));
260 psz = pszExtensions;
261 for (i = 0; ; i++)
262 {
263 while (*psz == ' ')
264 psz++;
265 if (!*psz)
266 break;
267
268 const char *pszEnd = strchr(psz, ' ');
269 AssertBreak(pszEnd);
270 size_t cch = pszEnd - psz;
271
272 uint32_t iColumn = i % RT_ELEMENTS(acchWidths);
273 if (iColumn == 0)
274 LogRel(("\nVMSVGA3d: %-*.*s", acchWidths[iColumn], cch, psz));
275 else if (iColumn != RT_ELEMENTS(acchWidths) - 1)
276 LogRel((" %-*.*s", acchWidths[iColumn], cch, psz));
277 else
278 LogRel((" %.*s", cch, psz));
279
280 psz = pszEnd;
281 }
282
283 RTLogRelSetBuffering(fBuffered);
284 LogRel(("\n"));
285}
286
287/**
288 * Gathers the GL_EXTENSIONS list, storing it as a space padded list at
289 * @a ppszExtensions.
290 *
291 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY
292 * @param ppszExtensions Pointer to the string pointer. Free with RTStrFree.
293 * @param fGLProfileVersion The OpenGL profile version.
294 */
295static int vmsvga3dGatherExtensions(char **ppszExtensions, float fGLProfileVersion)
296{
297 int rc;
298 *ppszExtensions = NULL;
299
300 /*
301 * Try the old glGetString interface first.
302 */
303 const char *pszExtensions = (const char *)glGetString(GL_EXTENSIONS);
304 if (pszExtensions)
305 {
306 rc = RTStrAAppendExN(ppszExtensions, 3, " ", (size_t)1, pszExtensions, RTSTR_MAX, " ", (size_t)1);
307 AssertLogRelRCReturn(rc, rc);
308 }
309 else
310 {
311 /*
312 * The new interface where each extension string is retrieved separately.
313 * Note! Cannot use VMSVGA3D_INIT_CHECKED_GL_GET_INTEGER_VALUE here because
314 * the above GL_EXTENSIONS error lingers on darwin. sucks.
315 */
316#ifndef GL_NUM_EXTENSIONS
317# define GL_NUM_EXTENSIONS 0x821D
318#endif
319 GLint cExtensions = 1024;
320 glGetIntegerv(GL_NUM_EXTENSIONS, &cExtensions);
321 Assert(cExtensions != 1024);
322
323 PFNGLGETSTRINGIPROC pfnGlGetStringi = (PFNGLGETSTRINGIPROC)OGLGETPROCADDRESS("glGetStringi");
324 AssertLogRelReturn(pfnGlGetStringi, VERR_NOT_SUPPORTED);
325
326 rc = RTStrAAppend(ppszExtensions, " ");
327 for (GLint i = 0; RT_SUCCESS(rc) && i < cExtensions; i++)
328 {
329 const char *pszExt = (const char *)pfnGlGetStringi(GL_EXTENSIONS, i);
330 if (pszExt)
331 rc = RTStrAAppendExN(ppszExtensions, 2, pfnGlGetStringi(GL_EXTENSIONS, i), RTSTR_MAX, " ", (size_t)1);
332 }
333 AssertRCReturn(rc, rc);
334 }
335
336#if 1
337 /*
338 * Add extensions promoted into the core OpenGL profile.
339 */
340 static const struct
341 {
342 float fGLVersion;
343 const char *pszzExtensions;
344 } s_aPromotedExtensions[] =
345 {
346 {
347 1.1f,
348 " GL_EXT_vertex_array \0"
349 " GL_EXT_polygon_offset \0"
350 " GL_EXT_blend_logic_op \0"
351 " GL_EXT_texture \0"
352 " GL_EXT_copy_texture \0"
353 " GL_EXT_subtexture \0"
354 " GL_EXT_texture_object \0"
355 " GL_ARB_framebuffer_object \0"
356 " GL_ARB_map_buffer_range \0"
357 " GL_ARB_vertex_array_object \0"
358 "\0"
359 },
360 {
361 1.2f,
362 " EXT_texture3D \0"
363 " EXT_bgra \0"
364 " EXT_packed_pixels \0"
365 " EXT_rescale_normal \0"
366 " EXT_separate_specular_color \0"
367 " SGIS_texture_edge_clamp \0"
368 " SGIS_texture_lod \0"
369 " EXT_draw_range_elements \0"
370 "\0"
371 },
372 {
373 1.3f,
374 " GL_ARB_texture_compression \0"
375 " GL_ARB_texture_cube_map \0"
376 " GL_ARB_multisample \0"
377 " GL_ARB_multitexture \0"
378 " GL_ARB_texture_env_add \0"
379 " GL_ARB_texture_env_combine \0"
380 " GL_ARB_texture_env_dot3 \0"
381 " GL_ARB_texture_border_clamp \0"
382 " GL_ARB_transpose_matrix \0"
383 "\0"
384 },
385 {
386 1.5f,
387 " GL_SGIS_generate_mipmap \0"
388 /*" GL_NV_blend_equare \0"*/
389 " GL_ARB_depth_texture \0"
390 " GL_ARB_shadow \0"
391 " GL_EXT_fog_coord \0"
392 " GL_EXT_multi_draw_arrays \0"
393 " GL_ARB_point_parameters \0"
394 " GL_EXT_secondary_color \0"
395 " GL_EXT_blend_func_separate \0"
396 " GL_EXT_stencil_wrap \0"
397 " GL_ARB_texture_env_crossbar \0"
398 " GL_EXT_texture_lod_bias \0"
399 " GL_ARB_texture_mirrored_repeat \0"
400 " GL_ARB_window_pos \0"
401 "\0"
402 },
403 {
404 1.6f,
405 " GL_ARB_vertex_buffer_object \0"
406 " GL_ARB_occlusion_query \0"
407 " GL_EXT_shadow_funcs \0"
408 },
409 {
410 2.0f,
411 " GL_ARB_shader_objects \0" /*??*/
412 " GL_ARB_vertex_shader \0" /*??*/
413 " GL_ARB_fragment_shader \0" /*??*/
414 " GL_ARB_shading_language_100 \0" /*??*/
415 " GL_ARB_draw_buffers \0"
416 " GL_ARB_texture_non_power_of_two \0"
417 " GL_ARB_point_sprite \0"
418 " GL_ATI_separate_stencil \0"
419 " GL_EXT_stencil_two_side \0"
420 "\0"
421 },
422 {
423 2.1f,
424 " GL_ARB_pixel_buffer_object \0"
425 " GL_EXT_texture_sRGB \0"
426 "\0"
427 },
428 {
429 3.0f,
430 " GL_ARB_framebuffer_object \0"
431 " GL_ARB_map_buffer_range \0"
432 " GL_ARB_vertex_array_object \0"
433 "\0"
434 },
435 {
436 3.1f,
437 " GL_ARB_copy_buffer \0"
438 " GL_ARB_uniform_buffer_object \0"
439 "\0"
440 },
441 {
442 3.2f,
443 " GL_ARB_vertex_array_bgra \0"
444 " GL_ARB_draw_elements_base_vertex \0"
445 " GL_ARB_fragment_coord_conventions \0"
446 " GL_ARB_provoking_vertex \0"
447 " GL_ARB_seamless_cube_map \0"
448 " GL_ARB_texture_multisample \0"
449 " GL_ARB_depth_clamp \0"
450 " GL_ARB_sync \0"
451 " GL_ARB_geometry_shader4 \0" /*??*/
452 "\0"
453 },
454 {
455 3.3f,
456 " GL_ARB_blend_func_extended \0"
457 " GL_ARB_sampler_objects \0"
458 " GL_ARB_explicit_attrib_location \0"
459 " GL_ARB_occlusion_query2 \0"
460 " GL_ARB_shader_bit_encoding \0"
461 " GL_ARB_texture_rgb10_a2ui \0"
462 " GL_ARB_texture_swizzle \0"
463 " GL_ARB_timer_query \0"
464 " GL_ARB_vertex_type_2_10_10_10_rev \0"
465 "\0"
466 },
467 {
468 4.0f,
469 " GL_ARB_texture_query_lod \0"
470 " GL_ARB_draw_indirect \0"
471 " GL_ARB_gpu_shader5 \0"
472 " GL_ARB_gpu_shader_fp64 \0"
473 " GL_ARB_shader_subroutine \0"
474 " GL_ARB_tessellation_shader \0"
475 " GL_ARB_texture_buffer_object_rgb32 \0"
476 " GL_ARB_texture_cube_map_array \0"
477 " GL_ARB_texture_gather \0"
478 " GL_ARB_transform_feedback2 \0"
479 " GL_ARB_transform_feedback3 \0"
480 "\0"
481 },
482 {
483 4.1f,
484 " GL_ARB_ES2_compatibility \0"
485 " GL_ARB_get_program_binary \0"
486 " GL_ARB_separate_shader_objects \0"
487 " GL_ARB_shader_precision \0"
488 " GL_ARB_vertex_attrib_64bit \0"
489 " GL_ARB_viewport_array \0"
490 "\0"
491 }
492 };
493
494 uint32_t cPromoted = 0;
495 for (uint32_t i = 0; i < RT_ELEMENTS(s_aPromotedExtensions) && s_aPromotedExtensions[i].fGLVersion <= fGLProfileVersion; i++)
496 {
497 const char *pszExt = s_aPromotedExtensions[i].pszzExtensions;
498 while (*pszExt)
499 {
500# ifdef VBOX_STRICT
501 size_t cchExt = strlen(pszExt);
502 Assert(cchExt > 3);
503 Assert(pszExt[0] == ' ');
504 Assert(pszExt[1] != ' ');
505 Assert(pszExt[cchExt - 2] != ' ');
506 Assert(pszExt[cchExt - 1] == ' ');
507# endif
508
509 if (strstr(*ppszExtensions, pszExt) == NULL)
510 {
511 if (cPromoted++ == 0)
512 {
513 rc = RTStrAAppend(ppszExtensions, " <promoted-extensions:> <promoted-extensions:> <promoted-extensions:> ");
514 AssertRCReturn(rc, rc);
515 }
516
517 rc = RTStrAAppend(ppszExtensions, pszExt);
518 AssertRCReturn(rc, rc);
519 }
520
521 pszExt = strchr(pszExt, '\0') + 1;
522 }
523 }
524#endif
525
526 return VINF_SUCCESS;
527}
528
529/** Check whether this is an Intel GL driver.
530 *
531 * @returns true if this seems to be some Intel graphics.
532 */
533static bool vmsvga3dIsVendorIntel(void)
534{
535 return RTStrNICmp((char *)glGetString(GL_VENDOR), "Intel", 5) == 0;
536}
537
538/**
539 * @interface_method_impl{VBOXVMSVGASHADERIF,pfnSwitchInitProfile}
540 */
541static DECLCALLBACK(void) vmsvga3dShaderIfSwitchInitProfile(PVBOXVMSVGASHADERIF pThis, bool fOtherProfile)
542{
543#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
544 PVMSVGA3DSTATE pState = RT_FROM_MEMBER(pThis, VMSVGA3DSTATE, ShaderIf);
545 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pState->papContexts[fOtherProfile ? 2 : 1]);
546#else
547 NOREF(pThis);
548 NOREF(fOtherProfile);
549#endif
550}
551
552
553/**
554 * @interface_method_impl{VBOXVMSVGASHADERIF,pfnGetNextExtension}
555 */
556static DECLCALLBACK(bool) vmsvga3dShaderIfGetNextExtension(PVBOXVMSVGASHADERIF pThis, void **ppvEnumCtx,
557 char *pszBuf, size_t cbBuf, bool fOtherProfile)
558{
559 PVMSVGA3DSTATE pState = RT_FROM_MEMBER(pThis, VMSVGA3DSTATE, ShaderIf);
560 const char *pszCur = *ppvEnumCtx ? (const char *)*ppvEnumCtx
561 : fOtherProfile ? pState->pszOtherExtensions : pState->pszExtensions;
562 while (*pszCur == ' ')
563 pszCur++;
564 if (!*pszCur)
565 return false;
566
567 const char *pszEnd = strchr(pszCur, ' ');
568 AssertReturn(pszEnd, false);
569 size_t cch = pszEnd - pszCur;
570 if (cch < cbBuf)
571 {
572 memcpy(pszBuf, pszCur, cch);
573 pszBuf[cch] = '\0';
574 }
575 else if (cbBuf > 0)
576 {
577 memcpy(pszBuf, "<overflow>", RT_MIN(sizeof("<overflow>"), cbBuf));
578 pszBuf[cbBuf - 1] = '\0';
579 }
580
581 *ppvEnumCtx = (void *)pszEnd;
582 return true;
583}
584
585
586/**
587 * Initializes the VMSVGA3D state during VGA device construction.
588 *
589 * Failure are generally not fatal, 3D support will just be disabled.
590 *
591 * @returns VBox status code.
592 * @param pDevIns The device instance.
593 * @param pThis The shared VGA/VMSVGA state where svga.p3dState will be
594 * modified.
595 * @param pThisCC The VGA/VMSVGA state for ring-3.
596 */
597static DECLCALLBACK(int) vmsvga3dBackInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
598{
599 int rc;
600 RT_NOREF(pDevIns, pThis);
601
602 AssertCompile(GL_TRUE == 1);
603 AssertCompile(GL_FALSE == 0);
604
605#ifdef VMSVGA3D_DYNAMIC_LOAD
606 rc = glLdrInit(pDevIns);
607 if (RT_FAILURE(rc))
608 {
609 LogRel(("VMSVGA3d: Error loading OpenGL library and resolving necessary functions: %Rrc\n", rc));
610 return rc;
611 }
612#endif
613
614 /*
615 * Load and resolve imports from the external shared libraries.
616 */
617 RTERRINFOSTATIC ErrInfo;
618 rc = ExplicitlyLoadVBoxSVGA3D(true /*fResolveAllImports*/, RTErrInfoInitStatic(&ErrInfo));
619 if (RT_FAILURE(rc))
620 {
621 LogRel(("VMSVGA3d: Error loading VBoxSVGA3D and resolving necessary functions: %Rrc - %s\n", rc, ErrInfo.Core.pszMsg));
622 return rc;
623 }
624#ifdef RT_OS_DARWIN
625 rc = ExplicitlyLoadVBoxSVGA3DObjC(true /*fResolveAllImports*/, RTErrInfoInitStatic(&ErrInfo));
626 if (RT_FAILURE(rc))
627 {
628 LogRel(("VMSVGA3d: Error loading VBoxSVGA3DObjC and resolving necessary functions: %Rrc - %s\n", rc, ErrInfo.Core.pszMsg));
629 return rc;
630 }
631#endif
632
633 /*
634 * Allocate the state.
635 */
636 pThisCC->svga.p3dState = (PVMSVGA3DSTATE)RTMemAllocZ(sizeof(VMSVGA3DSTATE));
637 AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY);
638
639#ifdef RT_OS_WINDOWS
640 /* Create event semaphore and async IO thread. */
641 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
642 rc = RTSemEventCreate(&pState->WndRequestSem);
643 if (RT_SUCCESS(rc))
644 {
645 rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dWindowThread, pState->WndRequestSem, 0, RTTHREADTYPE_GUI, 0,
646 "VMSVGA3DWND");
647 if (RT_SUCCESS(rc))
648 return VINF_SUCCESS;
649
650 /* bail out. */
651 LogRel(("VMSVGA3d: RTThreadCreate failed: %Rrc\n", rc));
652 RTSemEventDestroy(pState->WndRequestSem);
653 }
654 else
655 LogRel(("VMSVGA3d: RTSemEventCreate failed: %Rrc\n", rc));
656 RTMemFree(pThisCC->svga.p3dState);
657 pThisCC->svga.p3dState = NULL;
658 return rc;
659#else
660 return VINF_SUCCESS;
661#endif
662}
663
664static int vmsvga3dLoadGLFunctions(PVMSVGA3DSTATE pState)
665{
666 /* A strict approach to get a proc address as recommended by Khronos:
667 * - "If the function is a core OpenGL function, then we need to check the OpenGL version".
668 * - "If the function is an extension, we need to check to see if the extension is supported."
669 */
670
671/* Get a function address, return VERR_NOT_IMPLEMENTED on failure. */
672#define GLGETPROC_(ProcType, ProcName, NameSuffix) do { \
673 pState->ext.ProcName = (ProcType)OGLGETPROCADDRESS(#ProcName NameSuffix); \
674 AssertLogRelMsgReturn(pState->ext.ProcName, (#ProcName NameSuffix " missing"), VERR_NOT_IMPLEMENTED); \
675} while(0)
676
677/* Get an optional function address. LogRel on failure. */
678#define GLGETPROCOPT_(ProcType, ProcName, NameSuffix) do { \
679 pState->ext.ProcName = (ProcType)OGLGETPROCADDRESS(#ProcName NameSuffix); \
680 if (!pState->ext.ProcName) \
681 { \
682 LogRel(("VMSVGA3d: missing optional %s\n", #ProcName NameSuffix)); \
683 AssertFailed(); \
684 } \
685} while(0)
686
687 /* OpenGL 2.0 or earlier core. Do not bother with extensions. */
688 GLGETPROC_(PFNGLGENQUERIESPROC , glGenQueries, "");
689 GLGETPROC_(PFNGLDELETEQUERIESPROC , glDeleteQueries, "");
690 GLGETPROC_(PFNGLBEGINQUERYPROC , glBeginQuery, "");
691 GLGETPROC_(PFNGLENDQUERYPROC , glEndQuery, "");
692 GLGETPROC_(PFNGLGETQUERYOBJECTUIVPROC , glGetQueryObjectuiv, "");
693 GLGETPROC_(PFNGLTEXIMAGE3DPROC , glTexImage3D, "");
694 GLGETPROC_(PFNGLTEXSUBIMAGE3DPROC , glTexSubImage3D, "");
695 GLGETPROC_(PFNGLGETCOMPRESSEDTEXIMAGEPROC , glGetCompressedTexImage, "");
696 GLGETPROC_(PFNGLCOMPRESSEDTEXIMAGE2DPROC , glCompressedTexImage2D, "");
697 GLGETPROC_(PFNGLCOMPRESSEDTEXIMAGE3DPROC , glCompressedTexImage3D, "");
698 GLGETPROC_(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC , glCompressedTexSubImage2D, "");
699 GLGETPROC_(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC , glCompressedTexSubImage3D, "");
700 GLGETPROC_(PFNGLPOINTPARAMETERFPROC , glPointParameterf, "");
701 GLGETPROC_(PFNGLBLENDEQUATIONSEPARATEPROC , glBlendEquationSeparate, "");
702 GLGETPROC_(PFNGLBLENDFUNCSEPARATEPROC , glBlendFuncSeparate, "");
703 GLGETPROC_(PFNGLSTENCILOPSEPARATEPROC , glStencilOpSeparate, "");
704 GLGETPROC_(PFNGLSTENCILFUNCSEPARATEPROC , glStencilFuncSeparate, "");
705 GLGETPROC_(PFNGLBINDBUFFERPROC , glBindBuffer, "");
706 GLGETPROC_(PFNGLDELETEBUFFERSPROC , glDeleteBuffers, "");
707 GLGETPROC_(PFNGLGENBUFFERSPROC , glGenBuffers, "");
708 GLGETPROC_(PFNGLBUFFERDATAPROC , glBufferData, "");
709 GLGETPROC_(PFNGLMAPBUFFERPROC , glMapBuffer, "");
710 GLGETPROC_(PFNGLUNMAPBUFFERPROC , glUnmapBuffer, "");
711 GLGETPROC_(PFNGLENABLEVERTEXATTRIBARRAYPROC , glEnableVertexAttribArray, "");
712 GLGETPROC_(PFNGLDISABLEVERTEXATTRIBARRAYPROC , glDisableVertexAttribArray, "");
713 GLGETPROC_(PFNGLVERTEXATTRIBPOINTERPROC , glVertexAttribPointer, "");
714 GLGETPROC_(PFNGLACTIVETEXTUREPROC , glActiveTexture, "");
715 /* glGetProgramivARB determines implementation limits for the program
716 * target (GL_FRAGMENT_PROGRAM_ARB, GL_VERTEX_PROGRAM_ARB).
717 * It differs from glGetProgramiv, which returns a parameter from a program object.
718 */
719 GLGETPROC_(PFNGLGETPROGRAMIVARBPROC , glGetProgramivARB, "");
720 GLGETPROC_(PFNGLFOGCOORDPOINTERPROC , glFogCoordPointer, "");
721#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x102
722 GLGETPROC_(PFNGLBLENDCOLORPROC , glBlendColor, "");
723 GLGETPROC_(PFNGLBLENDEQUATIONPROC , glBlendEquation, "");
724#endif
725#if VBOX_VMSVGA3D_GL_HACK_LEVEL < 0x103
726 GLGETPROC_(PFNGLCLIENTACTIVETEXTUREPROC , glClientActiveTexture, "");
727#endif
728 GLGETPROC_(PFNGLDRAWBUFFERSPROC , glDrawBuffers, "");
729 GLGETPROC_(PFNGLCREATESHADERPROC , glCreateShader, "");
730 GLGETPROC_(PFNGLSHADERSOURCEPROC , glShaderSource, "");
731 GLGETPROC_(PFNGLCOMPILESHADERPROC , glCompileShader, "");
732 GLGETPROC_(PFNGLGETSHADERIVPROC , glGetShaderiv, "");
733 GLGETPROC_(PFNGLGETSHADERINFOLOGPROC , glGetShaderInfoLog, "");
734 GLGETPROC_(PFNGLCREATEPROGRAMPROC , glCreateProgram, "");
735 GLGETPROC_(PFNGLATTACHSHADERPROC , glAttachShader, "");
736 GLGETPROC_(PFNGLLINKPROGRAMPROC , glLinkProgram, "");
737 GLGETPROC_(PFNGLGETPROGRAMIVPROC , glGetProgramiv, "");
738 GLGETPROC_(PFNGLGETPROGRAMINFOLOGPROC , glGetProgramInfoLog, "");
739 GLGETPROC_(PFNGLUSEPROGRAMPROC , glUseProgram, "");
740 GLGETPROC_(PFNGLGETUNIFORMLOCATIONPROC , glGetUniformLocation, "");
741 GLGETPROC_(PFNGLUNIFORM1IPROC , glUniform1i, "");
742 GLGETPROC_(PFNGLUNIFORM4FVPROC , glUniform4fv, "");
743 GLGETPROC_(PFNGLDETACHSHADERPROC , glDetachShader, "");
744 GLGETPROC_(PFNGLDELETESHADERPROC , glDeleteShader, "");
745 GLGETPROC_(PFNGLDELETEPROGRAMPROC , glDeleteProgram, "");
746
747 GLGETPROC_(PFNGLVERTEXATTRIB4FVPROC , glVertexAttrib4fv, "");
748 GLGETPROC_(PFNGLVERTEXATTRIB4UBVPROC , glVertexAttrib4ubv, "");
749 GLGETPROC_(PFNGLVERTEXATTRIB4NUBVPROC , glVertexAttrib4Nubv, "");
750 GLGETPROC_(PFNGLVERTEXATTRIB4SVPROC , glVertexAttrib4sv, "");
751 GLGETPROC_(PFNGLVERTEXATTRIB4NSVPROC , glVertexAttrib4Nsv, "");
752 GLGETPROC_(PFNGLVERTEXATTRIB4NUSVPROC , glVertexAttrib4Nusv, "");
753
754 /* OpenGL 3.0 core, GL_ARB_instanced_arrays. Same functions names in the ARB and core specs. */
755 if ( pState->rsGLVersion >= 3.0f
756 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_framebuffer_object "))
757 {
758 GLGETPROC_(PFNGLISRENDERBUFFERPROC , glIsRenderbuffer, "");
759 GLGETPROC_(PFNGLBINDRENDERBUFFERPROC , glBindRenderbuffer, "");
760 GLGETPROC_(PFNGLDELETERENDERBUFFERSPROC , glDeleteRenderbuffers, "");
761 GLGETPROC_(PFNGLGENRENDERBUFFERSPROC , glGenRenderbuffers, "");
762 GLGETPROC_(PFNGLRENDERBUFFERSTORAGEPROC , glRenderbufferStorage, "");
763 GLGETPROC_(PFNGLGETRENDERBUFFERPARAMETERIVPROC , glGetRenderbufferParameteriv, "");
764 GLGETPROC_(PFNGLISFRAMEBUFFERPROC , glIsFramebuffer, "");
765 GLGETPROC_(PFNGLBINDFRAMEBUFFERPROC , glBindFramebuffer, "");
766 GLGETPROC_(PFNGLDELETEFRAMEBUFFERSPROC , glDeleteFramebuffers, "");
767 GLGETPROC_(PFNGLGENFRAMEBUFFERSPROC , glGenFramebuffers, "");
768 GLGETPROC_(PFNGLCHECKFRAMEBUFFERSTATUSPROC , glCheckFramebufferStatus, "");
769 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE1DPROC , glFramebufferTexture1D, "");
770 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE2DPROC , glFramebufferTexture2D, "");
771 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURE3DPROC , glFramebufferTexture3D, "");
772 GLGETPROC_(PFNGLFRAMEBUFFERRENDERBUFFERPROC , glFramebufferRenderbuffer, "");
773 GLGETPROC_(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC , glGetFramebufferAttachmentParameteriv, "");
774 GLGETPROC_(PFNGLGENERATEMIPMAPPROC , glGenerateMipmap, "");
775 GLGETPROC_(PFNGLBLITFRAMEBUFFERPROC , glBlitFramebuffer, "");
776 GLGETPROC_(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC , glRenderbufferStorageMultisample, "");
777 GLGETPROC_(PFNGLFRAMEBUFFERTEXTURELAYERPROC , glFramebufferTextureLayer, "");
778 }
779
780 /* OpenGL 3.1 core, GL_ARB_draw_instanced, GL_EXT_draw_instanced. */
781 if (pState->rsGLVersion >= 3.1f)
782 {
783 GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "");
784 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "");
785 }
786 else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_draw_instanced "))
787 {
788 GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "ARB");
789 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "ARB");
790 }
791 else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_draw_instanced "))
792 {
793 GLGETPROC_(PFNGLDRAWARRAYSINSTANCEDPROC , glDrawArraysInstanced, "EXT");
794 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDPROC , glDrawElementsInstanced, "EXT");
795 }
796
797 /* OpenGL 3.2 core, GL_ARB_draw_elements_base_vertex. Same functions names in the ARB and core specs. */
798 if ( pState->rsGLVersion >= 3.2f
799 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_draw_elements_base_vertex "))
800 {
801 GLGETPROC_(PFNGLDRAWELEMENTSBASEVERTEXPROC , glDrawElementsBaseVertex, "");
802 GLGETPROC_(PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC , glDrawElementsInstancedBaseVertex, "");
803 }
804
805 /* Optional. OpenGL 3.2 core, GL_ARB_provoking_vertex. Same functions names in the ARB and core specs. */
806 if ( pState->rsGLVersion >= 3.2f
807 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_provoking_vertex "))
808 {
809 GLGETPROCOPT_(PFNGLPROVOKINGVERTEXPROC , glProvokingVertex, "");
810 }
811
812 /* OpenGL 3.3 core, GL_ARB_instanced_arrays. */
813 if (pState->rsGLVersion >= 3.3f)
814 {
815 GLGETPROC_(PFNGLVERTEXATTRIBDIVISORPROC , glVertexAttribDivisor, "");
816 }
817 else if (vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_instanced_arrays "))
818 {
819 GLGETPROC_(PFNGLVERTEXATTRIBDIVISORARBPROC , glVertexAttribDivisor, "ARB");
820 }
821
822#undef GLGETPROCOPT_
823#undef GLGETPROC_
824
825 return VINF_SUCCESS;
826}
827
828
829DECLINLINE(GLenum) vmsvga3dCubemapFaceFromIndex(uint32_t iFace)
830{
831 GLint Face;
832 switch (iFace)
833 {
834 case 0: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; break;
835 case 1: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; break;
836 case 2: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; break;
837 case 3: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; break;
838 case 4: Face = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; break;
839 default:
840 case 5: Face = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; break;
841 }
842 return Face;
843}
844
845
846/* We must delay window creation until the PowerOn phase. Init is too early and will cause failures. */
847static DECLCALLBACK(int) vmsvga3dBackPowerOn(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
848{
849 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
850 AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY);
851 PVMSVGA3DCONTEXT pContext;
852#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
853 PVMSVGA3DCONTEXT pOtherCtx;
854#endif
855 int rc;
856 RT_NOREF(pDevIns, pThis);
857
858 if (pState->rsGLVersion != 0.0)
859 return VINF_SUCCESS; /* already initialized (load state) */
860
861 /*
862 * OpenGL function calls aren't possible without a valid current context, so create a fake one here.
863 */
864 rc = vmsvga3dContextDefineOgl(pThisCC, 1, VMSVGA3D_DEF_CTX_F_INIT);
865 AssertRCReturn(rc, rc);
866
867 pContext = pState->papContexts[1];
868 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
869
870#ifdef VMSVGA3D_DYNAMIC_LOAD
871 /* Context is set and it is possible now to resolve extension functions. */
872 rc = glLdrGetExtFunctions(pDevIns);
873 if (RT_FAILURE(rc))
874 {
875 LogRel(("VMSVGA3d: Error resolving extension functions: %Rrc\n", rc));
876 return rc;
877 }
878#endif
879
880 LogRel(("VMSVGA3d: OpenGL version: %s\n"
881 "VMSVGA3d: OpenGL Vendor: %s\n"
882 "VMSVGA3d: OpenGL Renderer: %s\n"
883 "VMSVGA3d: OpenGL shader language version: %s\n",
884 glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER),
885 glGetString(GL_SHADING_LANGUAGE_VERSION)));
886
887 rc = vmsvga3dGatherExtensions(&pState->pszExtensions, VBOX_VMSVGA3D_DEFAULT_OGL_PROFILE);
888 AssertRCReturn(rc, rc);
889 vmsvga3dLogRelExtensions("", pState->pszExtensions);
890
891 pState->rsGLVersion = atof((const char *)glGetString(GL_VERSION));
892
893
894#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
895 /*
896 * Get the extension list for the alternative profile so we can better
897 * figure out the shader model and stuff.
898 */
899 rc = vmsvga3dContextDefineOgl(pThisCC, 2, VMSVGA3D_DEF_CTX_F_INIT | VMSVGA3D_DEF_CTX_F_OTHER_PROFILE);
900 AssertLogRelRCReturn(rc, rc);
901 pContext = pState->papContexts[1]; /* Array may have been reallocated. */
902
903 pOtherCtx = pState->papContexts[2];
904 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx);
905
906 LogRel(("VMSVGA3d: Alternative OpenGL version: %s\n"
907 "VMSVGA3d: Alternative OpenGL Vendor: %s\n"
908 "VMSVGA3d: Alternative OpenGL Renderer: %s\n"
909 "VMSVGA3d: Alternative OpenGL shader language version: %s\n",
910 glGetString(GL_VERSION), glGetString(GL_VENDOR), glGetString(GL_RENDERER),
911 glGetString(GL_SHADING_LANGUAGE_VERSION)));
912
913 rc = vmsvga3dGatherExtensions(&pState->pszOtherExtensions, VBOX_VMSVGA3D_OTHER_OGL_PROFILE);
914 AssertRCReturn(rc, rc);
915 vmsvga3dLogRelExtensions("Alternative ", pState->pszOtherExtensions);
916
917 pState->rsOtherGLVersion = atof((const char *)glGetString(GL_VERSION));
918
919 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
920#else
921 pState->pszOtherExtensions = (char *)"";
922 pState->rsOtherGLVersion = pState->rsGLVersion;
923#endif
924
925 /*
926 * Resolve GL function pointers and store them in pState->ext.
927 */
928 rc = vmsvga3dLoadGLFunctions(pState);
929 if (RT_FAILURE(rc))
930 {
931 LogRel(("VMSVGA3d: missing required OpenGL function or extension; aborting\n"));
932 return rc;
933 }
934
935 /*
936 * Initialize the capabilities with sensible defaults.
937 */
938 pState->caps.maxActiveLights = 1;
939 pState->caps.maxTextures = 1;
940 pState->caps.maxClipDistances = 4;
941 pState->caps.maxColorAttachments = 1;
942 pState->caps.maxRectangleTextureSize = 2048;
943 pState->caps.maxTextureAnisotropy = 1;
944 pState->caps.maxVertexShaderInstructions = 1024;
945 pState->caps.maxFragmentShaderInstructions = 1024;
946 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_NONE;
947 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_NONE;
948 pState->caps.flPointSize[0] = 1;
949 pState->caps.flPointSize[1] = 1;
950
951 /*
952 * Query capabilities
953 */
954 pState->caps.fS3TCSupported = vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_texture_compression_s3tc ");
955 pState->caps.fTextureFilterAnisotropicSupported = vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_texture_filter_anisotropic ");
956
957 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetIntegerv(GL_MAX_LIGHTS, &pState->caps.maxActiveLights));
958 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &pState->caps.maxTextures));
959#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE /* The alternative profile has a higher number here (ati/darwin). */
960 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx);
961 VMSVGA3D_INIT_CHECKED_BOTH(pState, pOtherCtx, pContext, glGetIntegerv(GL_MAX_CLIP_DISTANCES, &pState->caps.maxClipDistances));
962 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
963#else
964 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_CLIP_DISTANCES, &pState->caps.maxClipDistances));
965#endif
966 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &pState->caps.maxColorAttachments));
967 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, &pState->caps.maxRectangleTextureSize));
968 if (pState->caps.fTextureFilterAnisotropicSupported)
969 VMSVGA3D_INIT_CHECKED(glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &pState->caps.maxTextureAnisotropy));
970 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx, glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pState->caps.flPointSize));
971
972 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
973 pState->ext.glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
974 &pState->caps.maxFragmentShaderTemps));
975 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
976 pState->ext.glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
977 &pState->caps.maxFragmentShaderInstructions));
978 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
979 pState->ext.glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
980 &pState->caps.maxVertexShaderTemps));
981 VMSVGA3D_INIT_CHECKED_BOTH(pState, pContext, pOtherCtx,
982 pState->ext.glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
983 &pState->caps.maxVertexShaderInstructions));
984
985 /* http://http://www.opengl.org/wiki/Detecting_the_Shader_Model
986 * ARB Assembly Language
987 * These are done through testing the presence of extensions. You should test them in this order:
988 * GL_NV_gpu_program4: SM 4.0 or better.
989 * GL_NV_vertex_program3: SM 3.0 or better.
990 * GL_ARB_fragment_program: SM 2.0 or better.
991 * ATI does not support higher than SM 2.0 functionality in assembly shaders.
992 *
993 */
994 /** @todo distinguish between vertex and pixel shaders??? */
995#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE /* The alternative profile has a higher number here (ati/darwin). */
996 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pOtherCtx);
997 const char *pszShadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
998 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
999#else
1000 const char *pszShadingLanguageVersion = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
1001#endif
1002 float v = pszShadingLanguageVersion ? atof(pszShadingLanguageVersion) : 0.0f;
1003 if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_NV_gpu_program4 ")
1004 || strstr(pState->pszOtherExtensions, " GL_NV_gpu_program4 "))
1005 {
1006 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_40;
1007 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_40;
1008 }
1009 else
1010 if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_NV_vertex_program3 ")
1011 || strstr(pState->pszOtherExtensions, " GL_NV_vertex_program3 ")
1012 || vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_shader_texture_lod ") /* Wine claims this suggests SM 3.0 support */
1013 || strstr(pState->pszOtherExtensions, " GL_ARB_shader_texture_lod ")
1014 )
1015 {
1016 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_30;
1017 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_30;
1018 }
1019 else
1020 if ( vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_fragment_program ")
1021 || strstr(pState->pszOtherExtensions, " GL_ARB_fragment_program "))
1022 {
1023 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_20;
1024 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_20;
1025 }
1026 else
1027 {
1028 LogRel(("VMSVGA3D: WARNING: unknown support for assembly shaders!!\n"));
1029 pState->caps.vertexShaderVersion = SVGA3DVSVERSION_11;
1030 pState->caps.fragmentShaderVersion = SVGA3DPSVERSION_11;
1031 }
1032
1033 /* Now check the shading language version, in case it indicates a higher supported version. */
1034 if (v >= 3.30f)
1035 {
1036 pState->caps.vertexShaderVersion = RT_MAX(pState->caps.vertexShaderVersion, SVGA3DVSVERSION_40);
1037 pState->caps.fragmentShaderVersion = RT_MAX(pState->caps.fragmentShaderVersion, SVGA3DPSVERSION_40);
1038 }
1039 else
1040 if (v >= 1.20f)
1041 {
1042 pState->caps.vertexShaderVersion = RT_MAX(pState->caps.vertexShaderVersion, SVGA3DVSVERSION_20);
1043 pState->caps.fragmentShaderVersion = RT_MAX(pState->caps.fragmentShaderVersion, SVGA3DPSVERSION_20);
1044 }
1045
1046 if ( !vmsvga3dCheckGLExtension(pState, 0.0f, " GL_ARB_vertex_array_bgra ")
1047 && !vmsvga3dCheckGLExtension(pState, 0.0f, " GL_EXT_vertex_array_bgra "))
1048 {
1049 LogRel(("VMSVGA3D: WARNING: Missing required extension GL_ARB_vertex_array_bgra (d3dcolor)!!!\n"));
1050 }
1051
1052 /*
1053 * Tweak capabilities.
1054 */
1055 /* Intel Windows drivers return 31, while the guest expects 32 at least. */
1056 if ( pState->caps.maxVertexShaderTemps < 32
1057 && vmsvga3dIsVendorIntel())
1058 pState->caps.maxVertexShaderTemps = 32;
1059
1060#if 0
1061 SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = 11,
1062 SVGA3D_DEVCAP_QUERY_TYPES = 15,
1063 SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = 16,
1064 SVGA3D_DEVCAP_MAX_POINT_SIZE = 17,
1065 SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = 18,
1066 SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = 21,
1067 SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = 22,
1068 SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = 23,
1069 SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = 24,
1070 SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = 25,
1071 SVGA3D_DEVCAP_MAX_VERTEX_INDEX = 26,
1072 SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = 28,
1073 SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = 29,
1074 SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = 30,
1075 SVGA3D_DEVCAP_TEXTURE_OPS = 31,
1076 SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = 32,
1077 SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = 33,
1078 SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = 34,
1079 SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = 35,
1080 SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = 36,
1081 SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = 37,
1082 SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = 38,
1083 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = 39,
1084 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = 40,
1085 SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = 41,
1086 SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = 42,
1087 SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = 43,
1088 SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = 44,
1089 SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = 45,
1090 SVGA3D_DEVCAP_SURFACEFMT_DXT1 = 46,
1091 SVGA3D_DEVCAP_SURFACEFMT_DXT2 = 47,
1092 SVGA3D_DEVCAP_SURFACEFMT_DXT3 = 48,
1093 SVGA3D_DEVCAP_SURFACEFMT_DXT4 = 49,
1094 SVGA3D_DEVCAP_SURFACEFMT_DXT5 = 50,
1095 SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = 51,
1096 SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = 52,
1097 SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = 53,
1098 SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = 54,
1099 SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = 55,
1100 SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = 56,
1101 SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = 57,
1102 SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = 58,
1103 SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = 59,
1104 SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = 60,
1105 SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = 61,
1106 SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = 63,
1107 SVGA3D_DEVCAP_SURFACEFMT_V16U16 = 65,
1108 SVGA3D_DEVCAP_SURFACEFMT_G16R16 = 66,
1109 SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67,
1110 SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68,
1111 SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69,
1112 SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = 70,
1113 SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = 71,
1114 SVGA3D_DEVCAP_ALPHATOCOVERAGE = 72,
1115 SVGA3D_DEVCAP_SUPERSAMPLE = 73,
1116 SVGA3D_DEVCAP_AUTOGENMIPMAPS = 74,
1117 SVGA3D_DEVCAP_SURFACEFMT_NV12 = 75,
1118 SVGA3D_DEVCAP_SURFACEFMT_AYUV = 76,
1119 SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = 79,
1120 SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = 80,
1121 SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = 81,
1122 SVGA3D_DEVCAP_SURFACEFMT_ATI1 = 82,
1123 SVGA3D_DEVCAP_SURFACEFMT_ATI2 = 83,
1124#endif
1125
1126 LogRel(("VMSVGA3d: Capabilities:\n"));
1127 LogRel(("VMSVGA3d: maxActiveLights=%-2d maxTextures=%-2d\n",
1128 pState->caps.maxActiveLights, pState->caps.maxTextures));
1129 LogRel(("VMSVGA3d: maxClipDistances=%-2d maxColorAttachments=%-2d maxClipDistances=%d\n",
1130 pState->caps.maxClipDistances, pState->caps.maxColorAttachments, pState->caps.maxClipDistances));
1131 LogRel(("VMSVGA3d: maxColorAttachments=%-2d maxTextureAnisotropy=%-2d maxRectangleTextureSize=%d\n",
1132 pState->caps.maxColorAttachments, pState->caps.maxTextureAnisotropy, pState->caps.maxRectangleTextureSize));
1133 LogRel(("VMSVGA3d: maxVertexShaderTemps=%-2d maxVertexShaderInstructions=%d maxFragmentShaderInstructions=%d\n",
1134 pState->caps.maxVertexShaderTemps, pState->caps.maxVertexShaderInstructions, pState->caps.maxFragmentShaderInstructions));
1135 LogRel(("VMSVGA3d: maxFragmentShaderTemps=%d flPointSize={%d.%02u, %d.%02u}\n",
1136 pState->caps.maxFragmentShaderTemps,
1137 (int)pState->caps.flPointSize[0], (int)(pState->caps.flPointSize[0] * 100) % 100,
1138 (int)pState->caps.flPointSize[1], (int)(pState->caps.flPointSize[1] * 100) % 100));
1139 LogRel(("VMSVGA3d: fragmentShaderVersion=%-2d vertexShaderVersion=%-2d\n",
1140 pState->caps.fragmentShaderVersion, pState->caps.vertexShaderVersion));
1141 LogRel(("VMSVGA3d: fS3TCSupported=%-2d fTextureFilterAnisotropicSupported=%d\n",
1142 pState->caps.fS3TCSupported, pState->caps.fTextureFilterAnisotropicSupported));
1143
1144
1145 /* Initialize the shader library. */
1146 pState->ShaderIf.pfnSwitchInitProfile = vmsvga3dShaderIfSwitchInitProfile;
1147 pState->ShaderIf.pfnGetNextExtension = vmsvga3dShaderIfGetNextExtension;
1148 rc = ShaderInitLib(&pState->ShaderIf);
1149 AssertRC(rc);
1150
1151 /* Cleanup */
1152 rc = vmsvga3dBackContextDestroy(pThisCC, 1);
1153 AssertRC(rc);
1154#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
1155 rc = vmsvga3dBackContextDestroy(pThisCC, 2);
1156 AssertRC(rc);
1157#endif
1158
1159 if ( pState->rsGLVersion < 3.0
1160 && pState->rsOtherGLVersion < 3.0 /* darwin: legacy profile hack */)
1161 {
1162 LogRel(("VMSVGA3d: unsupported OpenGL version; minimum is 3.0\n"));
1163 return VERR_NOT_IMPLEMENTED;
1164 }
1165
1166 return VINF_SUCCESS;
1167}
1168
1169static DECLCALLBACK(int) vmsvga3dBackReset(PVGASTATECC pThisCC)
1170{
1171 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1172 AssertReturn(pThisCC->svga.p3dState, VERR_NO_MEMORY);
1173
1174 /* Destroy all leftover surfaces. */
1175 for (uint32_t i = 0; i < pState->cSurfaces; i++)
1176 {
1177 if (pState->papSurfaces[i]->id != SVGA3D_INVALID_ID)
1178 vmsvga3dSurfaceDestroy(pThisCC, pState->papSurfaces[i]->id);
1179 }
1180
1181 /* Destroy all leftover contexts. */
1182 for (uint32_t i = 0; i < pState->cContexts; i++)
1183 {
1184 if (pState->papContexts[i]->id != SVGA3D_INVALID_ID)
1185 vmsvga3dBackContextDestroy(pThisCC, pState->papContexts[i]->id);
1186 }
1187
1188 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
1189 vmsvga3dContextDestroyOgl(pThisCC, &pState->SharedCtx, VMSVGA3D_SHARED_CTX_ID);
1190
1191 return VINF_SUCCESS;
1192}
1193
1194static DECLCALLBACK(int) vmsvga3dBackTerminate(PVGASTATECC pThisCC)
1195{
1196 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1197 AssertReturn(pState, VERR_WRONG_ORDER);
1198 int rc;
1199
1200 rc = vmsvga3dBackReset(pThisCC);
1201 AssertRCReturn(rc, rc);
1202
1203 /* Terminate the shader library. */
1204 rc = ShaderDestroyLib();
1205 AssertRC(rc);
1206
1207#ifdef RT_OS_WINDOWS
1208 /* Terminate the window creation thread. */
1209 rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_EXIT, 0, 0);
1210 AssertRCReturn(rc, rc);
1211
1212 RTSemEventDestroy(pState->WndRequestSem);
1213#elif defined(RT_OS_DARWIN)
1214
1215#elif defined(RT_OS_LINUX)
1216 /* signal to the thread that it is supposed to exit */
1217 pState->bTerminate = true;
1218 /* wait for it to terminate */
1219 rc = RTThreadWait(pState->pWindowThread, 10000, NULL);
1220 AssertRC(rc);
1221 XCloseDisplay(pState->display);
1222#endif
1223
1224 RTStrFree(pState->pszExtensions);
1225 pState->pszExtensions = NULL;
1226#ifdef VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE
1227 RTStrFree(pState->pszOtherExtensions);
1228#endif
1229 pState->pszOtherExtensions = NULL;
1230
1231 return VINF_SUCCESS;
1232}
1233
1234
1235static DECLCALLBACK(void) vmsvga3dBackUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport)
1236{
1237 /** @todo Move the visible framebuffer content here, don't wait for the guest to
1238 * redraw it. */
1239
1240#ifdef RT_OS_DARWIN
1241 RT_NOREF(pOldViewport);
1242 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1243 if ( pState
1244 && idScreen == 0
1245 && pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
1246 {
1247 vmsvga3dCocoaViewUpdateViewport(pState->SharedCtx.cocoaView);
1248 }
1249#else
1250 RT_NOREF(pThisCC, idScreen, pOldViewport);
1251#endif
1252}
1253
1254
1255/**
1256 * Worker for vmsvga3dBackQueryCaps that figures out supported operations for a
1257 * given surface format capability.
1258 *
1259 * @returns Supported/indented operations (SVGA3DFORMAT_OP_XXX).
1260 * @param idx3dCaps The SVGA3D_CAPS_XXX value of the surface format.
1261 *
1262 * @remarks See fromat_cap_table in svga_format.c (mesa/gallium) for a reference
1263 * of implicit guest expectations:
1264 * http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/svga_format.c
1265 */
1266static uint32_t vmsvga3dGetSurfaceFormatSupport(uint32_t idx3dCaps)
1267{
1268 uint32_t result = 0;
1269
1270 /** @todo missing:
1271 *
1272 * SVGA3DFORMAT_OP_PIXELSIZE
1273 */
1274
1275 switch (idx3dCaps)
1276 {
1277 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1278 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
1279 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
1280 result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB
1281 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
1282 | SVGA3DFORMAT_OP_DISPLAYMODE /* Should not be set for alpha formats. */
1283 | SVGA3DFORMAT_OP_3DACCELERATION; /* implies OP_DISPLAYMODE */
1284 break;
1285
1286 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
1287 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
1288 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
1289 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
1290 result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB
1291 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
1292 | SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET;
1293 break;
1294 }
1295
1296 /** @todo check hardware caps! */
1297 switch (idx3dCaps)
1298 {
1299 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1300 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
1301 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
1302 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
1303 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
1304 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
1305 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
1306 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
1307 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
1308 case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
1309 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
1310 result |= SVGA3DFORMAT_OP_TEXTURE
1311 | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET
1312 | SVGA3DFORMAT_OP_OFFSCREENPLAIN
1313 | SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
1314 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1315 | SVGA3DFORMAT_OP_CUBETEXTURE
1316 | SVGA3DFORMAT_OP_SRGBREAD
1317 | SVGA3DFORMAT_OP_SRGBWRITE;
1318 break;
1319
1320 case SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
1321 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
1322 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
1323 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
1324 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
1325 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
1326 result |= SVGA3DFORMAT_OP_ZSTENCIL
1327 | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
1328 | SVGA3DFORMAT_OP_TEXTURE /* Necessary for Ubuntu Unity */;
1329 break;
1330
1331 case SVGA3D_DEVCAP_SURFACEFMT_DXT1:
1332 case SVGA3D_DEVCAP_SURFACEFMT_DXT2:
1333 case SVGA3D_DEVCAP_SURFACEFMT_DXT3:
1334 case SVGA3D_DEVCAP_SURFACEFMT_DXT4:
1335 case SVGA3D_DEVCAP_SURFACEFMT_DXT5:
1336 result |= SVGA3DFORMAT_OP_TEXTURE
1337 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1338 | SVGA3DFORMAT_OP_CUBETEXTURE
1339 | SVGA3DFORMAT_OP_SRGBREAD;
1340 break;
1341
1342 case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
1343 case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
1344 case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
1345 case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
1346 case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
1347 break;
1348
1349 case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
1350 case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
1351 case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
1352 case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
1353 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
1354 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
1355 result |= SVGA3DFORMAT_OP_TEXTURE
1356 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1357 | SVGA3DFORMAT_OP_CUBETEXTURE
1358 | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
1359 break;
1360
1361 case SVGA3D_DEVCAP_SURFACEFMT_V16U16:
1362 case SVGA3D_DEVCAP_SURFACEFMT_G16R16:
1363 case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
1364 result |= SVGA3DFORMAT_OP_TEXTURE
1365 | SVGA3DFORMAT_OP_VOLUMETEXTURE
1366 | SVGA3DFORMAT_OP_CUBETEXTURE
1367 | SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET;
1368 break;
1369
1370 case SVGA3D_DEVCAP_SURFACEFMT_UYVY:
1371 case SVGA3D_DEVCAP_SURFACEFMT_YUY2:
1372 result |= SVGA3DFORMAT_OP_OFFSCREENPLAIN
1373 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
1374 | SVGA3DFORMAT_OP_TEXTURE;
1375 break;
1376
1377 case SVGA3D_DEVCAP_SURFACEFMT_NV12:
1378 case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */
1379 break;
1380 }
1381 Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result)));
1382
1383 return result;
1384}
1385
1386#if 0 /* unused */
1387static uint32_t vmsvga3dGetDepthFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps)
1388{
1389 RT_NOREF(pState3D, idx3dCaps);
1390
1391 /** @todo test this somehow */
1392 uint32_t result = SVGA3DFORMAT_OP_ZSTENCIL | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH;
1393
1394 Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result)));
1395 return result;
1396}
1397#endif
1398
1399
1400static DECLCALLBACK(int) vmsvga3dBackQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val)
1401{
1402 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1403 AssertReturn(pState, VERR_NO_MEMORY);
1404 int rc = VINF_SUCCESS;
1405
1406 *pu32Val = 0;
1407
1408 /*
1409 * The capabilities access by current (2015-03-01) linux sources (gallium,
1410 * vmwgfx, xorg-video-vmware) are annotated, caps without xref annotations
1411 * aren't access.
1412 */
1413
1414 switch (idx3dCaps)
1415 {
1416 /* Linux: vmwgfx_fifo.c in kmod; only used with SVGA_CAP_GBOBJECTS. */
1417 case SVGA3D_DEVCAP_3D:
1418 *pu32Val = 1; /* boolean? */
1419 break;
1420
1421 case SVGA3D_DEVCAP_MAX_LIGHTS:
1422 *pu32Val = pState->caps.maxActiveLights;
1423 break;
1424
1425 case SVGA3D_DEVCAP_MAX_TEXTURES:
1426 *pu32Val = pState->caps.maxTextures;
1427 break;
1428
1429 case SVGA3D_DEVCAP_MAX_CLIP_PLANES:
1430 *pu32Val = pState->caps.maxClipDistances;
1431 break;
1432
1433 /* Linux: svga_screen.c in gallium; 3.0 or later required. */
1434 case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
1435 *pu32Val = pState->caps.vertexShaderVersion;
1436 break;
1437
1438 case SVGA3D_DEVCAP_VERTEX_SHADER:
1439 /* boolean? */
1440 *pu32Val = (pState->caps.vertexShaderVersion != SVGA3DVSVERSION_NONE);
1441 break;
1442
1443 /* Linux: svga_screen.c in gallium; 3.0 or later required. */
1444 case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
1445 *pu32Val = pState->caps.fragmentShaderVersion;
1446 break;
1447
1448 case SVGA3D_DEVCAP_FRAGMENT_SHADER:
1449 /* boolean? */
1450 *pu32Val = (pState->caps.fragmentShaderVersion != SVGA3DPSVERSION_NONE);
1451 break;
1452
1453 case SVGA3D_DEVCAP_S23E8_TEXTURES:
1454 case SVGA3D_DEVCAP_S10E5_TEXTURES:
1455 /* Must be obsolete by now; surface format caps specify the same thing. */
1456 rc = VERR_INVALID_PARAMETER;
1457 break;
1458
1459 case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
1460 break;
1461
1462 /*
1463 * 2. The BUFFER_FORMAT capabilities are deprecated, and they always
1464 * return TRUE. Even on physical hardware that does not support
1465 * these formats natively, the SVGA3D device will provide an emulation
1466 * which should be invisible to the guest OS.
1467 */
1468 case SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
1469 case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
1470 case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
1471 *pu32Val = 1;
1472 break;
1473
1474 case SVGA3D_DEVCAP_QUERY_TYPES:
1475 break;
1476
1477 case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
1478 break;
1479
1480 /* Linux: svga_screen.c in gallium; capped at 80.0, default 1.0. */
1481 case SVGA3D_DEVCAP_MAX_POINT_SIZE:
1482 AssertCompile(sizeof(uint32_t) == sizeof(float));
1483 *(float *)pu32Val = pState->caps.flPointSize[1];
1484 break;
1485
1486 case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
1487 /** @todo ?? */
1488 rc = VERR_INVALID_PARAMETER;
1489 break;
1490
1491 /* Linux: svga_screen.c in gallium (for PIPE_CAP_MAX_TEXTURE_2D_LEVELS); have default if missing. */
1492 case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
1493 case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
1494 *pu32Val = pState->caps.maxRectangleTextureSize;
1495 break;
1496
1497 /* Linux: svga_screen.c in gallium (for PIPE_CAP_MAX_TEXTURE_3D_LEVELS); have default if missing. */
1498 case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
1499 //*pu32Val = pCaps->MaxVolumeExtent;
1500 *pu32Val = 256;
1501 break;
1502
1503 case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
1504 *pu32Val = 32768; /* hardcoded in Wine */
1505 break;
1506
1507 case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
1508 //*pu32Val = pCaps->MaxTextureAspectRatio;
1509 break;
1510
1511 /* Linux: svga_screen.c in gallium (for PIPE_CAPF_MAX_TEXTURE_ANISOTROPY); defaults to 4.0. */
1512 case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
1513 *pu32Val = pState->caps.maxTextureAnisotropy;
1514 break;
1515
1516 case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
1517 case SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
1518 *pu32Val = 0xFFFFF; /* hardcoded in Wine */
1519 break;
1520
1521 /* Linux: svga_screen.c in gallium (for PIPE_SHADER_VERTEX/PIPE_SHADER_CAP_MAX_INSTRUCTIONS); defaults to 512. */
1522 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
1523 *pu32Val = pState->caps.maxVertexShaderInstructions;
1524 break;
1525
1526 case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
1527 *pu32Val = pState->caps.maxFragmentShaderInstructions;
1528 break;
1529
1530 /* Linux: svga_screen.c in gallium (for PIPE_SHADER_VERTEX/PIPE_SHADER_CAP_MAX_TEMPS); defaults to 32. */
1531 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
1532 *pu32Val = pState->caps.maxVertexShaderTemps;
1533 break;
1534
1535 /* Linux: svga_screen.c in gallium (for PIPE_SHADER_FRAGMENT/PIPE_SHADER_CAP_MAX_TEMPS); defaults to 32. */
1536 case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
1537 *pu32Val = pState->caps.maxFragmentShaderTemps;
1538 break;
1539
1540 case SVGA3D_DEVCAP_TEXTURE_OPS:
1541 break;
1542
1543 case SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */
1544 break;
1545
1546 case SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */
1547 break;
1548
1549 case SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */
1550 break;
1551
1552 case SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */
1553 break;
1554
1555 case SVGA3D_DEVCAP_AUTOGENMIPMAPS:
1556 //*pu32Val = !!(pCaps->Caps2 & D3DCAPS2_CANAUTOGENMIPMAP);
1557 break;
1558
1559 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
1560 break;
1561
1562 case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: /** @todo same thing? */
1563 case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
1564 *pu32Val = pState->caps.maxColorAttachments;
1565 break;
1566
1567 /*
1568 * This is the maximum number of SVGA context IDs that the guest
1569 * can define using SVGA_3D_CMD_CONTEXT_DEFINE.
1570 */
1571 case SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
1572 *pu32Val = SVGA3D_MAX_CONTEXT_IDS;
1573 break;
1574
1575 /*
1576 * This is the maximum number of SVGA surface IDs that the guest
1577 * can define using SVGA_3D_CMD_SURFACE_DEFINE*.
1578 */
1579 case SVGA3D_DEVCAP_MAX_SURFACE_IDS:
1580 *pu32Val = SVGA3D_MAX_SURFACE_IDS;
1581 break;
1582
1583#if 0 /* Appeared more recently, not yet implemented. */
1584 /* Linux: svga_screen.c in gallium; defaults to FALSE. */
1585 case SVGA3D_DEVCAP_LINE_AA:
1586 break;
1587 /* Linux: svga_screen.c in gallium; defaults to FALSE. */
1588 case SVGA3D_DEVCAP_LINE_STIPPLE:
1589 break;
1590 /* Linux: svga_screen.c in gallium; defaults to 1.0. */
1591 case SVGA3D_DEVCAP_MAX_LINE_WIDTH:
1592 break;
1593 /* Linux: svga_screen.c in gallium; defaults to 1.0. */
1594 case SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH:
1595 break;
1596#endif
1597
1598 /*
1599 * Supported surface formats.
1600 * Linux: svga_format.c in gallium, format_cap_table defines implicit expectations.
1601 */
1602 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1603 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
1604 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
1605 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
1606 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
1607 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
1608 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
1609 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
1610 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
1611 case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
1612 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
1613 case SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
1614 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
1615 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
1616 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
1617 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
1618 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
1619 case SVGA3D_DEVCAP_SURFACEFMT_DXT1:
1620 *pu32Val = vmsvga3dGetSurfaceFormatSupport(idx3dCaps);
1621 break;
1622
1623 case SVGA3D_DEVCAP_SURFACEFMT_DXT2:
1624 case SVGA3D_DEVCAP_SURFACEFMT_DXT3:
1625 case SVGA3D_DEVCAP_SURFACEFMT_DXT4:
1626 case SVGA3D_DEVCAP_SURFACEFMT_DXT5:
1627 case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
1628 case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
1629 case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
1630 case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
1631 case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
1632 case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
1633 case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
1634 case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
1635 case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
1636 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
1637 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
1638 case SVGA3D_DEVCAP_SURFACEFMT_V16U16:
1639 case SVGA3D_DEVCAP_SURFACEFMT_G16R16:
1640 case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
1641 case SVGA3D_DEVCAP_SURFACEFMT_UYVY:
1642 case SVGA3D_DEVCAP_SURFACEFMT_YUY2:
1643 case SVGA3D_DEVCAP_SURFACEFMT_NV12:
1644 case SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */
1645 *pu32Val = vmsvga3dGetSurfaceFormatSupport(idx3dCaps);
1646 break;
1647
1648 /* Linux: Not referenced in current sources. */
1649 case SVGA3D_DEVCAP_SURFACEFMT_ATI1:
1650 case SVGA3D_DEVCAP_SURFACEFMT_ATI2:
1651 Log(("CAPS: Unknown CAP %s\n", vmsvga3dGetCapString(idx3dCaps)));
1652 rc = VERR_INVALID_PARAMETER;
1653 *pu32Val = 0;
1654 break;
1655
1656 default:
1657 Log(("CAPS: Unexpected CAP %d\n", idx3dCaps));
1658 rc = VERR_INVALID_PARAMETER;
1659 break;
1660 }
1661
1662 Log(("CAPS: %s - %x\n", vmsvga3dGetCapString(idx3dCaps), *pu32Val));
1663 return rc;
1664}
1665
1666/**
1667 * Convert SVGA format value to its OpenGL equivalent
1668 *
1669 * @remarks Clues to be had in format_texture_info table (wined3d/utils.c) with
1670 * help from wined3dformat_from_d3dformat().
1671 */
1672void vmsvga3dSurfaceFormat2OGL(PVMSVGA3DSURFACE pSurface, SVGA3dSurfaceFormat format)
1673{
1674#if 0
1675#define AssertTestFmt(f) AssertMsgFailed(("Test me - " #f "\n"))
1676#else
1677#define AssertTestFmt(f) do {} while(0)
1678#endif
1679 /* Init cbBlockGL for non-emulated formats. */
1680 pSurface->cbBlockGL = pSurface->cbBlock;
1681
1682 switch (format)
1683 {
1684 case SVGA3D_X8R8G8B8: /* D3DFMT_X8R8G8B8 - WINED3DFMT_B8G8R8X8_UNORM */
1685 pSurface->internalFormatGL = GL_RGB8;
1686 pSurface->formatGL = GL_BGRA;
1687 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1688 break;
1689 case SVGA3D_A8R8G8B8: /* D3DFMT_A8R8G8B8 - WINED3DFMT_B8G8R8A8_UNORM */
1690 pSurface->internalFormatGL = GL_RGBA8;
1691 pSurface->formatGL = GL_BGRA;
1692 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1693 break;
1694 case SVGA3D_R5G6B5: /* D3DFMT_R5G6B5 - WINED3DFMT_B5G6R5_UNORM */
1695 pSurface->internalFormatGL = GL_RGB5;
1696 pSurface->formatGL = GL_RGB;
1697 pSurface->typeGL = GL_UNSIGNED_SHORT_5_6_5;
1698 AssertTestFmt(SVGA3D_R5G6B5);
1699 break;
1700 case SVGA3D_X1R5G5B5: /* D3DFMT_X1R5G5B5 - WINED3DFMT_B5G5R5X1_UNORM */
1701 pSurface->internalFormatGL = GL_RGB5;
1702 pSurface->formatGL = GL_BGRA;
1703 pSurface->typeGL = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1704 AssertTestFmt(SVGA3D_X1R5G5B5);
1705 break;
1706 case SVGA3D_A1R5G5B5: /* D3DFMT_A1R5G5B5 - WINED3DFMT_B5G5R5A1_UNORM */
1707 pSurface->internalFormatGL = GL_RGB5_A1;
1708 pSurface->formatGL = GL_BGRA;
1709 pSurface->typeGL = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1710 AssertTestFmt(SVGA3D_A1R5G5B5);
1711 break;
1712 case SVGA3D_A4R4G4B4: /* D3DFMT_A4R4G4B4 - WINED3DFMT_B4G4R4A4_UNORM */
1713 pSurface->internalFormatGL = GL_RGBA4;
1714 pSurface->formatGL = GL_BGRA;
1715 pSurface->typeGL = GL_UNSIGNED_SHORT_4_4_4_4_REV;
1716 AssertTestFmt(SVGA3D_A4R4G4B4);
1717 break;
1718
1719 case SVGA3D_R8G8B8A8_UNORM:
1720 pSurface->internalFormatGL = GL_RGBA8;
1721 pSurface->formatGL = GL_RGBA;
1722 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1723 break;
1724
1725 case SVGA3D_Z_D32: /* D3DFMT_D32 - WINED3DFMT_D32_UNORM */
1726 pSurface->internalFormatGL = GL_DEPTH_COMPONENT32;
1727 pSurface->formatGL = GL_DEPTH_COMPONENT;
1728 pSurface->typeGL = GL_UNSIGNED_INT;
1729 break;
1730 case SVGA3D_Z_D16: /* D3DFMT_D16 - WINED3DFMT_D16_UNORM */
1731 pSurface->internalFormatGL = GL_DEPTH_COMPONENT16; /** @todo Wine suggests GL_DEPTH_COMPONENT24. */
1732 pSurface->formatGL = GL_DEPTH_COMPONENT;
1733 pSurface->typeGL = GL_UNSIGNED_SHORT;
1734 AssertTestFmt(SVGA3D_Z_D16);
1735 break;
1736 case SVGA3D_Z_D24S8: /* D3DFMT_D24S8 - WINED3DFMT_D24_UNORM_S8_UINT */
1737 pSurface->internalFormatGL = GL_DEPTH24_STENCIL8;
1738 pSurface->formatGL = GL_DEPTH_STENCIL;
1739 pSurface->typeGL = GL_UNSIGNED_INT_24_8;
1740 break;
1741 case SVGA3D_Z_D15S1: /* D3DFMT_D15S1 - WINED3DFMT_S1_UINT_D15_UNORM */
1742 pSurface->internalFormatGL = GL_DEPTH_COMPONENT16; /** @todo ??? */
1743 pSurface->formatGL = GL_DEPTH_STENCIL;
1744 pSurface->typeGL = GL_UNSIGNED_SHORT;
1745 /** @todo Wine sources hints at no hw support for this, so test this one! */
1746 AssertTestFmt(SVGA3D_Z_D15S1);
1747 break;
1748 case SVGA3D_Z_D24X8: /* D3DFMT_D24X8 - WINED3DFMT_X8D24_UNORM */
1749 pSurface->internalFormatGL = GL_DEPTH_COMPONENT24;
1750 pSurface->formatGL = GL_DEPTH_COMPONENT;
1751 pSurface->typeGL = GL_UNSIGNED_INT;
1752 AssertTestFmt(SVGA3D_Z_D24X8);
1753 break;
1754
1755 /* Advanced D3D9 depth formats. */
1756 case SVGA3D_Z_DF16: /* D3DFMT_DF16? - not supported */
1757 pSurface->internalFormatGL = GL_DEPTH_COMPONENT16;
1758 pSurface->formatGL = GL_DEPTH_COMPONENT;
1759 pSurface->typeGL = GL_HALF_FLOAT;
1760 break;
1761
1762 case SVGA3D_Z_DF24: /* D3DFMT_DF24? - not supported */
1763 pSurface->internalFormatGL = GL_DEPTH_COMPONENT24;
1764 pSurface->formatGL = GL_DEPTH_COMPONENT;
1765 pSurface->typeGL = GL_FLOAT; /* ??? */
1766 break;
1767
1768 case SVGA3D_Z_D24S8_INT: /* D3DFMT_D24S8 */
1769 pSurface->internalFormatGL = GL_DEPTH24_STENCIL8;
1770 pSurface->formatGL = GL_DEPTH_STENCIL;
1771 pSurface->typeGL = GL_UNSIGNED_INT_24_8;
1772 break;
1773
1774 case SVGA3D_DXT1: /* D3DFMT_DXT1 - WINED3DFMT_DXT1 */
1775 pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1776 pSurface->formatGL = GL_RGBA; /* not used */
1777 pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */
1778 break;
1779
1780 case SVGA3D_DXT2: /* D3DFMT_DXT2 */
1781 /* "DXT2 and DXT3 are the same from an API perspective." */
1782 RT_FALL_THRU();
1783 case SVGA3D_DXT3: /* D3DFMT_DXT3 - WINED3DFMT_DXT3 */
1784 pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
1785 pSurface->formatGL = GL_RGBA; /* not used */
1786 pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */
1787 break;
1788
1789 case SVGA3D_DXT4: /* D3DFMT_DXT4 */
1790 /* "DXT4 and DXT5 are the same from an API perspective." */
1791 RT_FALL_THRU();
1792 case SVGA3D_DXT5: /* D3DFMT_DXT5 - WINED3DFMT_DXT5 */
1793 pSurface->internalFormatGL = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
1794 pSurface->formatGL = GL_RGBA; /* not used */
1795 pSurface->typeGL = GL_UNSIGNED_BYTE; /* not used */
1796 break;
1797
1798 case SVGA3D_LUMINANCE8: /* D3DFMT_? - ? */
1799 pSurface->internalFormatGL = GL_LUMINANCE8_EXT;
1800 pSurface->formatGL = GL_LUMINANCE;
1801 pSurface->typeGL = GL_UNSIGNED_BYTE;
1802 break;
1803
1804 case SVGA3D_LUMINANCE16: /* D3DFMT_? - ? */
1805 pSurface->internalFormatGL = GL_LUMINANCE16_EXT;
1806 pSurface->formatGL = GL_LUMINANCE;
1807 pSurface->typeGL = GL_UNSIGNED_SHORT;
1808 break;
1809
1810 case SVGA3D_LUMINANCE4_ALPHA4: /* D3DFMT_? - ? */
1811 pSurface->internalFormatGL = GL_LUMINANCE4_ALPHA4_EXT;
1812 pSurface->formatGL = GL_LUMINANCE_ALPHA;
1813 pSurface->typeGL = GL_UNSIGNED_BYTE;
1814 break;
1815
1816 case SVGA3D_LUMINANCE8_ALPHA8: /* D3DFMT_? - ? */
1817 pSurface->internalFormatGL = GL_LUMINANCE8_ALPHA8_EXT;
1818 pSurface->formatGL = GL_LUMINANCE_ALPHA;
1819 pSurface->typeGL = GL_UNSIGNED_BYTE; /* unsigned_short causes issues even though this type should be 16-bit */
1820 break;
1821
1822 case SVGA3D_ALPHA8: /* D3DFMT_A8? - WINED3DFMT_A8_UNORM? */
1823 pSurface->internalFormatGL = GL_ALPHA8_EXT;
1824 pSurface->formatGL = GL_ALPHA;
1825 pSurface->typeGL = GL_UNSIGNED_BYTE;
1826 break;
1827
1828#if 0
1829
1830 /* Bump-map formats */
1831 case SVGA3D_BUMPU8V8:
1832 return D3DFMT_V8U8;
1833 case SVGA3D_BUMPL6V5U5:
1834 return D3DFMT_L6V5U5;
1835 case SVGA3D_BUMPX8L8V8U8:
1836 return D3DFMT_X8L8V8U8;
1837 case SVGA3D_FORMAT_DEAD1:
1838 /* No corresponding D3D9 equivalent. */
1839 AssertFailedReturn(D3DFMT_UNKNOWN);
1840 /* signed bump-map formats */
1841 case SVGA3D_V8U8:
1842 return D3DFMT_V8U8;
1843 case SVGA3D_Q8W8V8U8:
1844 return D3DFMT_Q8W8V8U8;
1845 case SVGA3D_CxV8U8:
1846 return D3DFMT_CxV8U8;
1847 /* mixed bump-map formats */
1848 case SVGA3D_X8L8V8U8:
1849 return D3DFMT_X8L8V8U8;
1850 case SVGA3D_A2W10V10U10:
1851 return D3DFMT_A2W10V10U10;
1852#endif
1853
1854 case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */ /* D3DFMT_A16B16G16R16F - WINED3DFMT_R16G16B16A16_FLOAT */
1855 pSurface->internalFormatGL = GL_RGBA16F;
1856 pSurface->formatGL = GL_RGBA;
1857#if 0 /* bird: wine uses half float, sounds correct to me... */
1858 pSurface->typeGL = GL_FLOAT;
1859#else
1860 pSurface->typeGL = GL_HALF_FLOAT;
1861 AssertTestFmt(SVGA3D_ARGB_S10E5);
1862#endif
1863 break;
1864
1865 case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */ /* D3DFMT_A32B32G32R32F - WINED3DFMT_R32G32B32A32_FLOAT */
1866 pSurface->internalFormatGL = GL_RGBA32F;
1867 pSurface->formatGL = GL_RGBA;
1868 pSurface->typeGL = GL_FLOAT; /* ?? - same as wine, so probably correct */
1869 break;
1870
1871 case SVGA3D_A2R10G10B10: /* D3DFMT_A2R10G10B10 - WINED3DFMT_B10G10R10A2_UNORM */
1872 pSurface->internalFormatGL = GL_RGB10_A2; /* ?? - same as wine, so probably correct */
1873#if 0 /* bird: Wine uses GL_BGRA instead of GL_RGBA. */
1874 pSurface->formatGL = GL_RGBA;
1875#else
1876 pSurface->formatGL = GL_BGRA;
1877#endif
1878 pSurface->typeGL = GL_UNSIGNED_INT;
1879 AssertTestFmt(SVGA3D_A2R10G10B10);
1880 break;
1881
1882
1883 /* Single- and dual-component floating point formats */
1884 case SVGA3D_R_S10E5: /* D3DFMT_R16F - WINED3DFMT_R16_FLOAT */
1885 pSurface->internalFormatGL = GL_R16F;
1886 pSurface->formatGL = GL_RED;
1887#if 0 /* bird: wine uses half float, sounds correct to me... */
1888 pSurface->typeGL = GL_FLOAT;
1889#else
1890 pSurface->typeGL = GL_HALF_FLOAT;
1891 AssertTestFmt(SVGA3D_R_S10E5);
1892#endif
1893 break;
1894 case SVGA3D_R_S23E8: /* D3DFMT_R32F - WINED3DFMT_R32_FLOAT */
1895 pSurface->internalFormatGL = GL_R32F;
1896 pSurface->formatGL = GL_RED;
1897 pSurface->typeGL = GL_FLOAT;
1898 break;
1899 case SVGA3D_RG_S10E5: /* D3DFMT_G16R16F - WINED3DFMT_R16G16_FLOAT */
1900 pSurface->internalFormatGL = GL_RG16F;
1901 pSurface->formatGL = GL_RG;
1902#if 0 /* bird: wine uses half float, sounds correct to me... */
1903 pSurface->typeGL = GL_FLOAT;
1904#else
1905 pSurface->typeGL = GL_HALF_FLOAT;
1906 AssertTestFmt(SVGA3D_RG_S10E5);
1907#endif
1908 break;
1909 case SVGA3D_RG_S23E8: /* D3DFMT_G32R32F - WINED3DFMT_R32G32_FLOAT */
1910 pSurface->internalFormatGL = GL_RG32F;
1911 pSurface->formatGL = GL_RG;
1912 pSurface->typeGL = GL_FLOAT;
1913 break;
1914
1915 /*
1916 * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
1917 * the most efficient format to use when creating new surfaces
1918 * expressly for index or vertex data.
1919 */
1920 case SVGA3D_BUFFER:
1921 pSurface->internalFormatGL = -1;
1922 pSurface->formatGL = -1;
1923 pSurface->typeGL = -1;
1924 break;
1925
1926#if 0
1927 return D3DFMT_UNKNOWN;
1928
1929 case SVGA3D_V16U16:
1930 return D3DFMT_V16U16;
1931#endif
1932
1933 case SVGA3D_G16R16: /* D3DFMT_G16R16 - WINED3DFMT_R16G16_UNORM */
1934 pSurface->internalFormatGL = GL_RG16;
1935 pSurface->formatGL = GL_RG;
1936#if 0 /* bird: Wine uses GL_UNSIGNED_SHORT here. */
1937 pSurface->typeGL = GL_UNSIGNED_INT;
1938#else
1939 pSurface->typeGL = GL_UNSIGNED_SHORT;
1940 AssertTestFmt(SVGA3D_G16R16);
1941#endif
1942 break;
1943
1944 case SVGA3D_A16B16G16R16: /* D3DFMT_A16B16G16R16 - WINED3DFMT_R16G16B16A16_UNORM */
1945 pSurface->internalFormatGL = GL_RGBA16;
1946 pSurface->formatGL = GL_RGBA;
1947#if 0 /* bird: Wine uses GL_UNSIGNED_SHORT here. */
1948 pSurface->typeGL = GL_UNSIGNED_INT; /* ??? */
1949#else
1950 pSurface->typeGL = GL_UNSIGNED_SHORT;
1951 AssertTestFmt(SVGA3D_A16B16G16R16);
1952#endif
1953 break;
1954
1955 case SVGA3D_R8G8B8A8_SNORM:
1956 pSurface->internalFormatGL = GL_RGB8;
1957 pSurface->formatGL = GL_BGRA;
1958 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1959 AssertTestFmt(SVGA3D_R8G8B8A8_SNORM);
1960 break;
1961 case SVGA3D_R16G16_UNORM:
1962 pSurface->internalFormatGL = GL_RG16;
1963 pSurface->formatGL = GL_RG;
1964 pSurface->typeGL = GL_UNSIGNED_SHORT;
1965 AssertTestFmt(SVGA3D_R16G16_UNORM);
1966 break;
1967
1968 /* Packed Video formats */
1969 case SVGA3D_UYVY:
1970 case SVGA3D_YUY2:
1971 /* Use a BRGA texture to hold the data and convert it to an actual BGRA. */
1972 pSurface->fEmulated = true;
1973 pSurface->internalFormatGL = GL_RGBA8;
1974 pSurface->formatGL = GL_BGRA;
1975 pSurface->typeGL = GL_UNSIGNED_INT_8_8_8_8_REV;
1976 pSurface->cbBlockGL = 4 * pSurface->cxBlock * pSurface->cyBlock;
1977 break;
1978
1979#if 0
1980 /* Planar video formats */
1981 case SVGA3D_NV12:
1982 return (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2');
1983
1984 /* Video format with alpha */
1985 case SVGA3D_FORMAT_DEAD2: /* Old SVGA3D_AYUV */
1986
1987 case SVGA3D_ATI1:
1988 case SVGA3D_ATI2:
1989 /* Unknown; only in DX10 & 11 */
1990 break;
1991#endif
1992 default:
1993 AssertMsgFailed(("Unsupported format %d\n", format));
1994 break;
1995 }
1996#undef AssertTestFmt
1997}
1998
1999
2000#if 0
2001/**
2002 * Convert SVGA multi sample count value to its D3D equivalent
2003 */
2004D3DMULTISAMPLE_TYPE vmsvga3dMultipeSampleCount2D3D(uint32_t multisampleCount)
2005{
2006 AssertCompile(D3DMULTISAMPLE_2_SAMPLES == 2);
2007 AssertCompile(D3DMULTISAMPLE_16_SAMPLES == 16);
2008
2009 if (multisampleCount > 16)
2010 return D3DMULTISAMPLE_NONE;
2011
2012 /** @todo exact same mapping as d3d? */
2013 return (D3DMULTISAMPLE_TYPE)multisampleCount;
2014}
2015#endif
2016
2017/**
2018 * Destroy backend specific surface bits (part of SVGA_3D_CMD_SURFACE_DESTROY).
2019 *
2020 * @param pThisCC The device state.
2021 * @param pSurface The surface being destroyed.
2022 */
2023static DECLCALLBACK(void) vmsvga3dBackSurfaceDestroy(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface)
2024{
2025 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
2026 AssertReturnVoid(pState);
2027
2028 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
2029 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
2030
2031 switch (pSurface->enmOGLResType)
2032 {
2033 case VMSVGA3D_OGLRESTYPE_BUFFER:
2034 Assert(pSurface->oglId.buffer != OPENGL_INVALID_ID);
2035 pState->ext.glDeleteBuffers(1, &pSurface->oglId.buffer);
2036 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2037 break;
2038
2039 case VMSVGA3D_OGLRESTYPE_TEXTURE:
2040 Assert(pSurface->oglId.texture != OPENGL_INVALID_ID);
2041 glDeleteTextures(1, &pSurface->oglId.texture);
2042 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2043 if (pSurface->fEmulated)
2044 {
2045 if (pSurface->idEmulated)
2046 {
2047 glDeleteTextures(1, &pSurface->idEmulated);
2048 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2049 }
2050 }
2051 else
2052 {
2053 Assert(!pSurface->idEmulated);
2054 }
2055 break;
2056
2057 case VMSVGA3D_OGLRESTYPE_RENDERBUFFER:
2058 Assert(pSurface->oglId.renderbuffer != OPENGL_INVALID_ID);
2059 pState->ext.glDeleteRenderbuffers(1, &pSurface->oglId.renderbuffer);
2060 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2061 break;
2062
2063 default:
2064 AssertMsg(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface),
2065 ("hint=%#x, type=%d\n",
2066 (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK), pSurface->enmOGLResType));
2067 break;
2068 }
2069}
2070
2071
2072static DECLCALLBACK(int) vmsvga3dBackSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src,
2073 uint32_t cCopyBoxes, SVGA3dCopyBox *pBox)
2074{
2075 int rc;
2076
2077 LogFunc(("Copy %d boxes from sid=%u face=%u mipmap=%u to sid=%u face=%u mipmap=%u\n",
2078 cCopyBoxes, src.sid, src.face, src.mipmap, dest.sid, dest.face, dest.mipmap));
2079
2080 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
2081 AssertReturn(pState, VERR_INVALID_STATE);
2082
2083 PVMSVGA3DSURFACE pSurfaceSrc;
2084 rc = vmsvga3dSurfaceFromSid(pState, src.sid, &pSurfaceSrc);
2085 AssertRCReturn(rc, rc);
2086
2087 PVMSVGA3DSURFACE pSurfaceDst;
2088 rc = vmsvga3dSurfaceFromSid(pState, dest.sid, &pSurfaceDst);
2089 AssertRCReturn(rc, rc);
2090
2091 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurfaceSrc))
2092 {
2093 /* The source surface is still in memory. */
2094 PVMSVGA3DMIPMAPLEVEL pMipmapLevelSrc;
2095 rc = vmsvga3dMipmapLevel(pSurfaceSrc, src.face, src.mipmap, &pMipmapLevelSrc);
2096 AssertRCReturn(rc, rc);
2097
2098 PVMSVGA3DMIPMAPLEVEL pMipmapLevelDst;
2099 rc = vmsvga3dMipmapLevel(pSurfaceDst, dest.face, dest.mipmap, &pMipmapLevelDst);
2100 AssertRCReturn(rc, rc);
2101
2102 /* The copy operation is performed on the shared context. */
2103 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
2104 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
2105
2106 /* Use glTexSubImage to upload the data to the destination texture.
2107 * The latter must be an OpenGL texture.
2108 */
2109 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurfaceDst))
2110 {
2111 LogFunc(("dest sid=%u type=0x%x format=%d -> create texture\n", dest.sid, pSurfaceDst->surfaceFlags, pSurfaceDst->format));
2112 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, pContext->id, pSurfaceDst);
2113 AssertRCReturn(rc, rc);
2114 }
2115
2116 GLenum target;
2117 if (pSurfaceDst->targetGL == GL_TEXTURE_CUBE_MAP)
2118 target = vmsvga3dCubemapFaceFromIndex(dest.face);
2119 else
2120 {
2121 AssertMsg(pSurfaceDst->targetGL == GL_TEXTURE_2D, ("Test %#x\n", pSurfaceDst->targetGL));
2122 target = pSurfaceDst->targetGL;
2123 }
2124
2125 /* Save the unpacking parameters and set what we need here. */
2126 VMSVGAPACKPARAMS SavedParams;
2127 vmsvga3dOglSetUnpackParams(pState, pContext,
2128 pMipmapLevelSrc->mipmapSize.width,
2129 target == GL_TEXTURE_3D ? pMipmapLevelSrc->mipmapSize.height : 0,
2130 &SavedParams);
2131
2132 glBindTexture(pSurfaceDst->targetGL, pSurfaceDst->oglId.texture);
2133 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2134
2135 for (uint32_t i = 0; i < cCopyBoxes; ++i)
2136 {
2137 SVGA3dCopyBox clipBox = pBox[i];
2138 vmsvgaR3ClipCopyBox(&pMipmapLevelSrc->mipmapSize, &pMipmapLevelDst->mipmapSize, &clipBox);
2139 if ( !clipBox.w
2140 || !clipBox.h
2141 || !clipBox.d)
2142 {
2143 LogFunc(("Skipped empty box.\n"));
2144 continue;
2145 }
2146
2147 LogFunc(("copy box %d,%d,%d %dx%d to %d,%d,%d\n",
2148 clipBox.srcx, clipBox.srcy, clipBox.srcz, clipBox.w, clipBox.h, clipBox.x, clipBox.y, clipBox.z));
2149
2150 uint32_t const u32BlockX = clipBox.srcx / pSurfaceSrc->cxBlock;
2151 uint32_t const u32BlockY = clipBox.srcy / pSurfaceSrc->cyBlock;
2152 uint32_t const u32BlockZ = clipBox.srcz;
2153 Assert(u32BlockX * pSurfaceSrc->cxBlock == clipBox.srcx);
2154 Assert(u32BlockY * pSurfaceSrc->cyBlock == clipBox.srcy);
2155
2156 uint8_t const *pSrcBits = (uint8_t *)pMipmapLevelSrc->pSurfaceData
2157 + pMipmapLevelSrc->cbSurfacePlane * u32BlockZ
2158 + pMipmapLevelSrc->cbSurfacePitch * u32BlockY
2159 + pSurfaceSrc->cbBlock * u32BlockX;
2160
2161 if (target == GL_TEXTURE_3D)
2162 {
2163 if ( pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2164 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2165 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2166 {
2167 uint32_t const cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock;
2168 uint32_t const cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock;
2169 uint32_t const imageSize = cBlocksX * cBlocksY * clipBox.d * pSurfaceSrc->cbBlock;
2170 pState->ext.glCompressedTexSubImage3D(target, dest.mipmap,
2171 clipBox.x, clipBox.y, clipBox.z,
2172 clipBox.w, clipBox.h, clipBox.d,
2173 pSurfaceSrc->internalFormatGL, (GLsizei)imageSize, pSrcBits);
2174 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2175 }
2176 else
2177 {
2178 pState->ext.glTexSubImage3D(target, dest.mipmap,
2179 clipBox.x, clipBox.y, clipBox.z,
2180 clipBox.w, clipBox.h, clipBox.d,
2181 pSurfaceSrc->formatGL, pSurfaceSrc->typeGL, pSrcBits);
2182 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2183 }
2184 }
2185 else
2186 {
2187 if ( pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2188 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2189 || pSurfaceDst->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2190 {
2191 uint32_t const cBlocksX = (clipBox.w + pSurfaceSrc->cxBlock - 1) / pSurfaceSrc->cxBlock;
2192 uint32_t const cBlocksY = (clipBox.h + pSurfaceSrc->cyBlock - 1) / pSurfaceSrc->cyBlock;
2193 uint32_t const imageSize = cBlocksX * cBlocksY * pSurfaceSrc->cbBlock;
2194 pState->ext.glCompressedTexSubImage2D(target, dest.mipmap,
2195 clipBox.x, clipBox.y, clipBox.w, clipBox.h,
2196 pSurfaceSrc->internalFormatGL, (GLsizei)imageSize, pSrcBits);
2197 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2198 }
2199 else
2200 {
2201 glTexSubImage2D(target, dest.mipmap,
2202 clipBox.x, clipBox.y, clipBox.w, clipBox.h,
2203 pSurfaceSrc->formatGL, pSurfaceSrc->typeGL, pSrcBits);
2204 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2205 }
2206 }
2207 }
2208
2209 glBindTexture(pSurfaceDst->targetGL, 0);
2210 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2211
2212 vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams);
2213
2214 return VINF_SUCCESS;
2215 }
2216
2217 PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
2218 for (uint32_t i = 0; i < cCopyBoxes; i++)
2219 {
2220 SVGA3dBox destBox, srcBox;
2221
2222 srcBox.x = pBox[i].srcx;
2223 srcBox.y = pBox[i].srcy;
2224 srcBox.z = pBox[i].srcz;
2225 srcBox.w = pBox[i].w;
2226 srcBox.h = pBox[i].h;
2227 srcBox.d = pBox[i].d;
2228
2229 destBox.x = pBox[i].x;
2230 destBox.y = pBox[i].y;
2231 destBox.z = pBox[i].z;
2232 destBox.w = pBox[i].w;
2233 destBox.h = pBox[i].h;
2234 destBox.d = pBox[i].d;
2235
2236 /* No stretching is required, therefore use SVGA3D_STRETCH_BLT_POINT which translated to GL_NEAREST. */
2237 rc = vmsvga3dSurfaceStretchBlt(pThis, pThisCC, &dest, &destBox, &src, &srcBox, SVGA3D_STRETCH_BLT_POINT);
2238 AssertRCReturn(rc, rc);
2239 }
2240 return VINF_SUCCESS;
2241}
2242
2243
2244/**
2245 * Saves texture unpacking parameters and loads the specified ones.
2246 *
2247 * @param pState The VMSVGA3D state structure.
2248 * @param pContext The active context.
2249 * @param cxRow The number of pixels in a row. 0 for the entire width.
2250 * @param cyImage The height of the image in pixels. 0 for the entire height.
2251 * @param pSave Where to save stuff.
2252 */
2253void vmsvga3dOglSetUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, GLint cxRow, GLint cyImage,
2254 PVMSVGAPACKPARAMS pSave)
2255{
2256 RT_NOREF(pState);
2257
2258 /*
2259 * Save (ignore errors, setting the defaults we want and avoids restore).
2260 */
2261 pSave->iAlignment = 1;
2262 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_ALIGNMENT, &pSave->iAlignment), pState, pContext);
2263 pSave->cxRow = 0;
2264 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_ROW_LENGTH, &pSave->cxRow), pState, pContext);
2265 pSave->cyImage = 0;
2266 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &pSave->cyImage), pState, pContext);
2267
2268#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2269 pSave->fSwapBytes = GL_FALSE;
2270 glGetBooleanv(GL_UNPACK_SWAP_BYTES, &pSave->fSwapBytes);
2271 Assert(pSave->fSwapBytes == GL_FALSE);
2272
2273 pSave->fLsbFirst = GL_FALSE;
2274 glGetBooleanv(GL_UNPACK_LSB_FIRST, &pSave->fLsbFirst);
2275 Assert(pSave->fLsbFirst == GL_FALSE);
2276
2277 pSave->cSkipRows = 0;
2278 glGetIntegerv(GL_UNPACK_SKIP_ROWS, &pSave->cSkipRows);
2279 Assert(pSave->cSkipRows == 0);
2280
2281 pSave->cSkipPixels = 0;
2282 glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &pSave->cSkipPixels);
2283 Assert(pSave->cSkipPixels == 0);
2284
2285 pSave->cSkipImages = 0;
2286 glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &pSave->cSkipImages);
2287 Assert(pSave->cSkipImages == 0);
2288
2289 VMSVGA3D_CLEAR_GL_ERRORS();
2290#endif
2291
2292 /*
2293 * Setup unpack.
2294 *
2295 * Note! We use 1 as alignment here because we currently don't do any
2296 * aligning of line pitches anywhere.
2297 */
2298 pSave->fChanged = 0;
2299 if (pSave->iAlignment != 1)
2300 {
2301 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1), pState, pContext);
2302 pSave->fChanged |= VMSVGAPACKPARAMS_ALIGNMENT;
2303 }
2304 if (pSave->cxRow != cxRow)
2305 {
2306 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, cxRow), pState, pContext);
2307 pSave->fChanged |= VMSVGAPACKPARAMS_ROW_LENGTH;
2308 }
2309 if (pSave->cyImage != cyImage)
2310 {
2311 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, cyImage), pState, pContext);
2312 pSave->fChanged |= VMSVGAPACKPARAMS_IMAGE_HEIGHT;
2313 }
2314#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2315 if (pSave->fSwapBytes != 0)
2316 {
2317 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE), pState, pContext);
2318 pSave->fChanged |= VMSVGAPACKPARAMS_SWAP_BYTES;
2319 }
2320 if (pSave->fLsbFirst != 0)
2321 {
2322 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE), pState, pContext);
2323 pSave->fChanged |= VMSVGAPACKPARAMS_LSB_FIRST;
2324 }
2325 if (pSave->cSkipRows != 0)
2326 {
2327 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS, 0), pState, pContext);
2328 pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_ROWS;
2329 }
2330 if (pSave->cSkipPixels != 0)
2331 {
2332 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0), pState, pContext);
2333 pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_PIXELS;
2334 }
2335 if (pSave->cSkipImages != 0)
2336 {
2337 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0), pState, pContext);
2338 pSave->fChanged |= VMSVGAPACKPARAMS_SKIP_IMAGES;
2339 }
2340#endif
2341}
2342
2343
2344/**
2345 * Restores texture unpacking parameters.
2346 *
2347 * @param pState The VMSVGA3D state structure.
2348 * @param pContext The active context.
2349 * @param pSave Where stuff was saved.
2350 */
2351void vmsvga3dOglRestoreUnpackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext,
2352 PCVMSVGAPACKPARAMS pSave)
2353{
2354 RT_NOREF(pState);
2355
2356 if (pSave->fChanged & VMSVGAPACKPARAMS_ALIGNMENT)
2357 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, pSave->iAlignment), pState, pContext);
2358 if (pSave->fChanged & VMSVGAPACKPARAMS_ROW_LENGTH)
2359 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, pSave->cxRow), pState, pContext);
2360 if (pSave->fChanged & VMSVGAPACKPARAMS_IMAGE_HEIGHT)
2361 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, pSave->cyImage), pState, pContext);
2362#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2363 if (pSave->fChanged & VMSVGAPACKPARAMS_SWAP_BYTES)
2364 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SWAP_BYTES, pSave->fSwapBytes), pState, pContext);
2365 if (pSave->fChanged & VMSVGAPACKPARAMS_LSB_FIRST)
2366 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_LSB_FIRST, pSave->fLsbFirst), pState, pContext);
2367 if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_ROWS)
2368 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS, pSave->cSkipRows), pState, pContext);
2369 if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_PIXELS)
2370 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS, pSave->cSkipPixels), pState, pContext);
2371 if (pSave->fChanged & VMSVGAPACKPARAMS_SKIP_IMAGES)
2372 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_UNPACK_SKIP_IMAGES, pSave->cSkipImages), pState, pContext);
2373#endif
2374}
2375
2376/**
2377 * Create D3D/OpenGL texture object for the specified surface.
2378 *
2379 * Surfaces are created when needed.
2380 *
2381 * @param pThisCC The device context.
2382 * @param pContext The context.
2383 * @param idAssociatedContext Probably the same as pContext->id.
2384 * @param pSurface The surface to create the texture for.
2385 */
2386static DECLCALLBACK(int) vmsvga3dBackCreateTexture(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext,
2387 PVMSVGA3DSURFACE pSurface)
2388{
2389 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
2390
2391 RT_NOREF(idAssociatedContext);
2392
2393 LogFunc(("sid=%u\n", pSurface->id));
2394
2395 uint32_t const numMipLevels = pSurface->cLevels;
2396
2397 /* Fugure out what kind of texture we are creating. */
2398 GLenum binding;
2399 GLenum target;
2400 if (pSurface->surfaceFlags & SVGA3D_SURFACE_CUBEMAP)
2401 {
2402 Assert(pSurface->cFaces == 6);
2403
2404 binding = GL_TEXTURE_BINDING_CUBE_MAP;
2405 target = GL_TEXTURE_CUBE_MAP;
2406 }
2407 else
2408 {
2409 if (pSurface->paMipmapLevels[0].mipmapSize.depth > 1)
2410 {
2411 binding = GL_TEXTURE_BINDING_3D;
2412 target = GL_TEXTURE_3D;
2413 }
2414 else
2415 {
2416 Assert(pSurface->cFaces == 1);
2417
2418 binding = GL_TEXTURE_BINDING_2D;
2419 target = GL_TEXTURE_2D;
2420 }
2421 }
2422
2423 /* All textures are created in the SharedCtx. */
2424 uint32_t idPrevCtx = pState->idActiveContext;
2425 pContext = &pState->SharedCtx;
2426 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
2427
2428 glGenTextures(1, &pSurface->oglId.texture);
2429 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2430 if (pSurface->fEmulated)
2431 {
2432 glGenTextures(1, &pSurface->idEmulated);
2433 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2434 }
2435 pSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_TEXTURE;
2436
2437 GLint activeTexture = 0;
2438 glGetIntegerv(binding, &activeTexture);
2439 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2440
2441 /* Must bind texture to the current context in order to change it. */
2442 glBindTexture(target, pSurface->oglId.texture);
2443 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2444
2445 /* Set the unpacking parameters. */
2446 VMSVGAPACKPARAMS SavedParams;
2447 vmsvga3dOglSetUnpackParams(pState, pContext, 0, 0, &SavedParams);
2448
2449 /** @todo Set the mip map generation filter settings. */
2450
2451 /* Set the mipmap base and max level parameters. */
2452 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
2453 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2454 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, pSurface->cLevels - 1);
2455 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2456
2457 if (pSurface->fDirty)
2458 LogFunc(("sync dirty texture\n"));
2459
2460 /* Always allocate and initialize all mipmap levels; non-initialized mipmap levels used as render targets cause failures. */
2461 if (target == GL_TEXTURE_3D)
2462 {
2463 for (uint32_t i = 0; i < numMipLevels; ++i)
2464 {
2465 /* Allocate and initialize texture memory. Passing the zero filled pSurfaceData avoids
2466 * exposing random host memory to the guest and helps a with the fedora 21 surface
2467 * corruption issues (launchpad, background, search field, login).
2468 */
2469 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i];
2470
2471 LogFunc(("sync dirty 3D texture mipmap level %d (pitch %x) (dirty %d)\n",
2472 i, pMipLevel->cbSurfacePitch, pMipLevel->fDirty));
2473
2474 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2475 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2476 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2477 {
2478 pState->ext.glCompressedTexImage3D(GL_TEXTURE_3D,
2479 i,
2480 pSurface->internalFormatGL,
2481 pMipLevel->mipmapSize.width,
2482 pMipLevel->mipmapSize.height,
2483 pMipLevel->mipmapSize.depth,
2484 0,
2485 pMipLevel->cbSurface,
2486 pMipLevel->pSurfaceData);
2487 }
2488 else
2489 {
2490 pState->ext.glTexImage3D(GL_TEXTURE_3D,
2491 i,
2492 pSurface->internalFormatGL,
2493 pMipLevel->mipmapSize.width,
2494 pMipLevel->mipmapSize.height,
2495 pMipLevel->mipmapSize.depth,
2496 0, /* border */
2497 pSurface->formatGL,
2498 pSurface->typeGL,
2499 pMipLevel->pSurfaceData);
2500 }
2501 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2502
2503 pMipLevel->fDirty = false;
2504 }
2505 }
2506 else if (target == GL_TEXTURE_CUBE_MAP)
2507 {
2508 for (uint32_t iFace = 0; iFace < 6; ++iFace)
2509 {
2510 GLenum const Face = vmsvga3dCubemapFaceFromIndex(iFace);
2511
2512 for (uint32_t i = 0; i < numMipLevels; ++i)
2513 {
2514 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[iFace * numMipLevels + i];
2515 Assert(pMipLevel->mipmapSize.width == pMipLevel->mipmapSize.height);
2516 Assert(pMipLevel->mipmapSize.depth == 1);
2517
2518 LogFunc(("sync cube texture face %d mipmap level %d (dirty %d)\n",
2519 iFace, i, pMipLevel->fDirty));
2520
2521 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2522 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2523 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2524 {
2525 pState->ext.glCompressedTexImage2D(Face,
2526 i,
2527 pSurface->internalFormatGL,
2528 pMipLevel->mipmapSize.width,
2529 pMipLevel->mipmapSize.height,
2530 0,
2531 pMipLevel->cbSurface,
2532 pMipLevel->pSurfaceData);
2533 }
2534 else
2535 {
2536 glTexImage2D(Face,
2537 i,
2538 pSurface->internalFormatGL,
2539 pMipLevel->mipmapSize.width,
2540 pMipLevel->mipmapSize.height,
2541 0,
2542 pSurface->formatGL,
2543 pSurface->typeGL,
2544 pMipLevel->pSurfaceData);
2545 }
2546 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2547
2548 pMipLevel->fDirty = false;
2549 }
2550 }
2551 }
2552 else if (target == GL_TEXTURE_2D)
2553 {
2554 for (uint32_t i = 0; i < numMipLevels; ++i)
2555 {
2556 /* Allocate and initialize texture memory. Passing the zero filled pSurfaceData avoids
2557 * exposing random host memory to the guest and helps a with the fedora 21 surface
2558 * corruption issues (launchpad, background, search field, login).
2559 */
2560 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i];
2561 Assert(pMipLevel->mipmapSize.depth == 1);
2562
2563 LogFunc(("sync dirty texture mipmap level %d (pitch %x) (dirty %d)\n",
2564 i, pMipLevel->cbSurfacePitch, pMipLevel->fDirty));
2565
2566 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2567 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2568 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2569 {
2570 pState->ext.glCompressedTexImage2D(GL_TEXTURE_2D,
2571 i,
2572 pSurface->internalFormatGL,
2573 pMipLevel->mipmapSize.width,
2574 pMipLevel->mipmapSize.height,
2575 0,
2576 pMipLevel->cbSurface,
2577 pMipLevel->pSurfaceData);
2578 }
2579 else
2580 {
2581 glTexImage2D(GL_TEXTURE_2D,
2582 i,
2583 pSurface->internalFormatGL,
2584 pMipLevel->mipmapSize.width,
2585 pMipLevel->mipmapSize.height,
2586 0,
2587 pSurface->formatGL,
2588 pSurface->typeGL,
2589 NULL);
2590 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2591
2592 if (pSurface->fEmulated)
2593 {
2594 /* Bind the emulated texture and init it. */
2595 glBindTexture(GL_TEXTURE_2D, pSurface->idEmulated);
2596 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2597
2598 glTexImage2D(GL_TEXTURE_2D,
2599 i,
2600 pSurface->internalFormatGL,
2601 pMipLevel->mipmapSize.width,
2602 pMipLevel->mipmapSize.height,
2603 0,
2604 pSurface->formatGL,
2605 pSurface->typeGL,
2606 NULL);
2607 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2608 }
2609
2610 /* Fetch texture data: either to the actual or to the emulated texture.
2611 * The pSurfaceData buffer may be smaller than the entire texture
2612 * for emulated formats, in which case only part of the texture is synched.
2613 */
2614 uint32_t cBlocksX = pMipLevel->mipmapSize.width / pSurface->cxBlock;
2615 uint32_t cBlocksY = pMipLevel->mipmapSize.height / pSurface->cyBlock;
2616 glTexSubImage2D(GL_TEXTURE_2D,
2617 i,
2618 0,
2619 0,
2620 cBlocksX,
2621 cBlocksY,
2622 pSurface->formatGL,
2623 pSurface->typeGL,
2624 pMipLevel->pSurfaceData);
2625 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2626
2627 if (pSurface->fEmulated)
2628 {
2629 /* Update the actual texture using the format converter. */
2630 FormatConvUpdateTexture(pState, pContext, pSurface, i);
2631
2632 /* Rebind the actual texture. */
2633 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
2634 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2635 }
2636 }
2637 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2638
2639 pMipLevel->fDirty = false;
2640 }
2641 }
2642
2643 pSurface->fDirty = false;
2644
2645 /* Restore unpacking parameters. */
2646 vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams);
2647
2648 /* Restore the old active texture. */
2649 glBindTexture(target, activeTexture);
2650 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2651
2652 pSurface->surfaceFlags |= SVGA3D_SURFACE_HINT_TEXTURE;
2653 pSurface->targetGL = target;
2654 pSurface->bindingGL = binding;
2655
2656 if (idPrevCtx < pState->cContexts && pState->papContexts[idPrevCtx]->id == idPrevCtx)
2657 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pState->papContexts[idPrevCtx]);
2658 return VINF_SUCCESS;
2659}
2660
2661
2662/**
2663 * Backend worker for implementing SVGA_3D_CMD_SURFACE_STRETCHBLT.
2664 *
2665 * @returns VBox status code.
2666 * @param pThis The VGA device instance.
2667 * @param pState The VMSVGA3d state.
2668 * @param pDstSurface The destination host surface.
2669 * @param uDstFace The destination face (valid).
2670 * @param uDstMipmap The destination mipmap level (valid).
2671 * @param pDstBox The destination box.
2672 * @param pSrcSurface The source host surface.
2673 * @param uSrcFace The destination face (valid).
2674 * @param uSrcMipmap The source mimap level (valid).
2675 * @param pSrcBox The source box.
2676 * @param enmMode The strecht blt mode .
2677 * @param pContext The VMSVGA3d context (already current for OGL).
2678 */
2679static DECLCALLBACK(int) vmsvga3dBackSurfaceStretchBlt(PVGASTATE pThis, PVMSVGA3DSTATE pState,
2680 PVMSVGA3DSURFACE pDstSurface, uint32_t uDstFace, uint32_t uDstMipmap, SVGA3dBox const *pDstBox,
2681 PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcFace, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox,
2682 SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext)
2683{
2684 RT_NOREF(pThis);
2685
2686 AssertReturn( RT_BOOL(pSrcSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
2687 == RT_BOOL(pDstSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL), VERR_NOT_IMPLEMENTED);
2688
2689 GLenum glAttachment = GL_COLOR_ATTACHMENT0;
2690 GLbitfield glMask = GL_COLOR_BUFFER_BIT;
2691 if (pDstSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
2692 {
2693 /** @todo Need GL_DEPTH_STENCIL_ATTACHMENT for depth/stencil formats? */
2694 glAttachment = GL_DEPTH_ATTACHMENT;
2695 glMask = GL_DEPTH_BUFFER_BIT;
2696 }
2697
2698 /* Activate the read and draw framebuffer objects. */
2699 pState->ext.glBindFramebuffer(GL_READ_FRAMEBUFFER, pContext->idReadFramebuffer);
2700 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2701 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pContext->idDrawFramebuffer);
2702 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2703
2704 /* Bind the source and destination objects to the right place. */
2705 GLenum textarget;
2706 if (pSrcSurface->targetGL == GL_TEXTURE_CUBE_MAP)
2707 textarget = vmsvga3dCubemapFaceFromIndex(uSrcFace);
2708 else
2709 {
2710 /// @todo later AssertMsg(pSrcSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pSrcSurface->targetGL));
2711 textarget = GL_TEXTURE_2D;
2712 }
2713 pState->ext.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, textarget,
2714 pSrcSurface->oglId.texture, uSrcMipmap);
2715 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2716
2717 if (pDstSurface->targetGL == GL_TEXTURE_CUBE_MAP)
2718 textarget = vmsvga3dCubemapFaceFromIndex(uDstFace);
2719 else
2720 {
2721 /// @todo later AssertMsg(pDstSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pDstSurface->targetGL));
2722 textarget = GL_TEXTURE_2D;
2723 }
2724 pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, textarget,
2725 pDstSurface->oglId.texture, uDstMipmap);
2726 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2727
2728 Log(("src conv. (%d,%d)(%d,%d); dest conv (%d,%d)(%d,%d)\n",
2729 pSrcBox->x, D3D_TO_OGL_Y_COORD(pSrcSurface, pSrcBox->y + pSrcBox->h),
2730 pSrcBox->x + pSrcBox->w, D3D_TO_OGL_Y_COORD(pSrcSurface, pSrcBox->y),
2731 pDstBox->x, D3D_TO_OGL_Y_COORD(pDstSurface, pDstBox->y + pDstBox->h),
2732 pDstBox->x + pDstBox->w, D3D_TO_OGL_Y_COORD(pDstSurface, pDstBox->y)));
2733
2734 pState->ext.glBlitFramebuffer(pSrcBox->x,
2735 pSrcBox->y,
2736 pSrcBox->x + pSrcBox->w, /* exclusive. */
2737 pSrcBox->y + pSrcBox->h,
2738 pDstBox->x,
2739 pDstBox->y,
2740 pDstBox->x + pDstBox->w, /* exclusive. */
2741 pDstBox->y + pDstBox->h,
2742 glMask,
2743 (enmMode == SVGA3D_STRETCH_BLT_POINT) ? GL_NEAREST : GL_LINEAR);
2744 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2745
2746 /* Reset the frame buffer association */
2747 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, pContext->idFramebuffer);
2748 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
2749
2750 return VINF_SUCCESS;
2751}
2752
2753/**
2754 * Save texture packing parameters and loads those appropriate for the given
2755 * surface.
2756 *
2757 * @param pState The VMSVGA3D state structure.
2758 * @param pContext The active context.
2759 * @param pSurface The surface.
2760 * @param pSave Where to save stuff.
2761 */
2762void vmsvga3dOglSetPackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface,
2763 PVMSVGAPACKPARAMS pSave)
2764{
2765 RT_NOREF(pState);
2766 /*
2767 * Save (ignore errors, setting the defaults we want and avoids restore).
2768 */
2769 pSave->iAlignment = 1;
2770 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_PACK_ALIGNMENT, &pSave->iAlignment), pState, pContext);
2771 pSave->cxRow = 0;
2772 VMSVGA3D_ASSERT_GL_CALL(glGetIntegerv(GL_PACK_ROW_LENGTH, &pSave->cxRow), pState, pContext);
2773
2774#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2775 pSave->cyImage = 0;
2776 glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &pSave->cyImage);
2777 Assert(pSave->cyImage == 0);
2778
2779 pSave->fSwapBytes = GL_FALSE;
2780 glGetBooleanv(GL_PACK_SWAP_BYTES, &pSave->fSwapBytes);
2781 Assert(pSave->fSwapBytes == GL_FALSE);
2782
2783 pSave->fLsbFirst = GL_FALSE;
2784 glGetBooleanv(GL_PACK_LSB_FIRST, &pSave->fLsbFirst);
2785 Assert(pSave->fLsbFirst == GL_FALSE);
2786
2787 pSave->cSkipRows = 0;
2788 glGetIntegerv(GL_PACK_SKIP_ROWS, &pSave->cSkipRows);
2789 Assert(pSave->cSkipRows == 0);
2790
2791 pSave->cSkipPixels = 0;
2792 glGetIntegerv(GL_PACK_SKIP_PIXELS, &pSave->cSkipPixels);
2793 Assert(pSave->cSkipPixels == 0);
2794
2795 pSave->cSkipImages = 0;
2796 glGetIntegerv(GL_PACK_SKIP_IMAGES, &pSave->cSkipImages);
2797 Assert(pSave->cSkipImages == 0);
2798
2799 VMSVGA3D_CLEAR_GL_ERRORS();
2800#endif
2801
2802 /*
2803 * Setup unpack.
2804 *
2805 * Note! We use 1 as alignment here because we currently don't do any
2806 * aligning of line pitches anywhere.
2807 */
2808 NOREF(pSurface);
2809 if (pSave->iAlignment != 1)
2810 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 1), pState, pContext);
2811 if (pSave->cxRow != 0)
2812 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ROW_LENGTH, 0), pState, pContext);
2813#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2814 if (pSave->cyImage != 0)
2815 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0), pState, pContext);
2816 if (pSave->fSwapBytes != 0)
2817 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE), pState, pContext);
2818 if (pSave->fLsbFirst != 0)
2819 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_LSB_FIRST, GL_FALSE), pState, pContext);
2820 if (pSave->cSkipRows != 0)
2821 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_ROWS, 0), pState, pContext);
2822 if (pSave->cSkipPixels != 0)
2823 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_PIXELS, 0), pState, pContext);
2824 if (pSave->cSkipImages != 0)
2825 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_IMAGES, 0), pState, pContext);
2826#endif
2827}
2828
2829
2830/**
2831 * Restores texture packing parameters.
2832 *
2833 * @param pState The VMSVGA3D state structure.
2834 * @param pContext The active context.
2835 * @param pSurface The surface.
2836 * @param pSave Where stuff was saved.
2837 */
2838void vmsvga3dOglRestorePackParams(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface,
2839 PCVMSVGAPACKPARAMS pSave)
2840{
2841 RT_NOREF(pState, pSurface);
2842 if (pSave->iAlignment != 1)
2843 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, pSave->iAlignment), pState, pContext);
2844 if (pSave->cxRow != 0)
2845 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_ROW_LENGTH, pSave->cxRow), pState, pContext);
2846#ifdef VMSVGA3D_PARANOID_TEXTURE_PACKING
2847 if (pSave->cyImage != 0)
2848 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_IMAGE_HEIGHT, pSave->cyImage), pState, pContext);
2849 if (pSave->fSwapBytes != 0)
2850 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SWAP_BYTES, pSave->fSwapBytes), pState, pContext);
2851 if (pSave->fLsbFirst != 0)
2852 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_LSB_FIRST, pSave->fLsbFirst), pState, pContext);
2853 if (pSave->cSkipRows != 0)
2854 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_ROWS, pSave->cSkipRows), pState, pContext);
2855 if (pSave->cSkipPixels != 0)
2856 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_PIXELS, pSave->cSkipPixels), pState, pContext);
2857 if (pSave->cSkipImages != 0)
2858 VMSVGA3D_ASSERT_GL_CALL(glPixelStorei(GL_PACK_SKIP_IMAGES, pSave->cSkipImages), pState, pContext);
2859#endif
2860}
2861
2862
2863/**
2864 * Backend worker for implementing SVGA_3D_CMD_SURFACE_DMA that copies one box.
2865 *
2866 * @returns Failure status code or @a rc.
2867 * @param pThis The shared VGA/VMSVGA instance data.
2868 * @param pThisCC The VGA/VMSVGA state for ring-3.
2869 * @param pState The VMSVGA3d state.
2870 * @param pSurface The host surface.
2871 * @param pMipLevel Mipmap level. The caller knows it already.
2872 * @param uHostFace The host face (valid).
2873 * @param uHostMipmap The host mipmap level (valid).
2874 * @param GuestPtr The guest pointer.
2875 * @param cbGuestPitch The guest pitch.
2876 * @param transfer The transfer direction.
2877 * @param pBox The box to copy (clipped, valid, except for guest's srcx, srcy, srcz).
2878 * @param pContext The context (for OpenGL).
2879 * @param rc The current rc for all boxes.
2880 * @param iBox The current box number (for Direct 3D).
2881 */
2882static DECLCALLBACK(int) vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface,
2883 PVMSVGA3DMIPMAPLEVEL pMipLevel, uint32_t uHostFace, uint32_t uHostMipmap,
2884 SVGAGuestPtr GuestPtr, uint32_t cbGuestPitch, SVGA3dTransferType transfer,
2885 SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox)
2886{
2887 RT_NOREF(iBox);
2888
2889 switch (pSurface->enmOGLResType)
2890 {
2891 case VMSVGA3D_OGLRESTYPE_TEXTURE:
2892 {
2893 uint32_t cbSurfacePitch;
2894 uint8_t *pDoubleBuffer;
2895 uint64_t offHst;
2896
2897 uint32_t const u32HostBlockX = pBox->x / pSurface->cxBlock;
2898 uint32_t const u32HostBlockY = pBox->y / pSurface->cyBlock;
2899 uint32_t const u32HostZ = pBox->z;
2900 Assert(u32HostBlockX * pSurface->cxBlock == pBox->x);
2901 Assert(u32HostBlockY * pSurface->cyBlock == pBox->y);
2902
2903 uint32_t const u32GuestBlockX = pBox->srcx / pSurface->cxBlock;
2904 uint32_t const u32GuestBlockY = pBox->srcy / pSurface->cyBlock;
2905 uint32_t const u32GuestZ = pBox->srcz / pSurface->cyBlock;
2906 Assert(u32GuestBlockX * pSurface->cxBlock == pBox->srcx);
2907 Assert(u32GuestBlockY * pSurface->cyBlock == pBox->srcy);
2908
2909 uint32_t const cBlocksX = (pBox->w + pSurface->cxBlock - 1) / pSurface->cxBlock;
2910 uint32_t const cBlocksY = (pBox->h + pSurface->cyBlock - 1) / pSurface->cyBlock;
2911 AssertMsgReturn(cBlocksX && cBlocksY, ("Empty box %dx%d\n", pBox->w, pBox->h), VERR_INTERNAL_ERROR);
2912
2913 GLenum texImageTarget;
2914 if (pSurface->targetGL == GL_TEXTURE_3D)
2915 {
2916 texImageTarget = GL_TEXTURE_3D;
2917 }
2918 else if (pSurface->targetGL == GL_TEXTURE_CUBE_MAP)
2919 {
2920 texImageTarget = vmsvga3dCubemapFaceFromIndex(uHostFace);
2921 }
2922 else
2923 {
2924 AssertMsg(pSurface->targetGL == GL_TEXTURE_2D, ("%#x\n", pSurface->targetGL));
2925 texImageTarget = GL_TEXTURE_2D;
2926 }
2927
2928 /* The buffer must be large enough to hold entire texture in the OpenGL format. */
2929 pDoubleBuffer = (uint8_t *)RTMemAlloc(pSurface->cbBlockGL * pMipLevel->cBlocks);
2930 AssertReturn(pDoubleBuffer, VERR_NO_MEMORY);
2931
2932 if (transfer == SVGA3D_READ_HOST_VRAM)
2933 {
2934 /* Read the entire texture to the double buffer. */
2935 GLint activeTexture;
2936
2937 /* Must bind texture to the current context in order to read it. */
2938 glGetIntegerv(pSurface->bindingGL, &activeTexture);
2939 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2940
2941 glBindTexture(pSurface->targetGL, GLTextureId(pSurface));
2942 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2943
2944 if (pSurface->fEmulated)
2945 {
2946 FormatConvReadTexture(pState, pContext, pSurface, uHostMipmap);
2947 }
2948
2949 /* Set row length and alignment of the input data. */
2950 VMSVGAPACKPARAMS SavedParams;
2951 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
2952
2953 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2954 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2955 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
2956 {
2957 pState->ext.glGetCompressedTexImage(texImageTarget, uHostMipmap, pDoubleBuffer);
2958 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2959 }
2960 else
2961 {
2962 glGetTexImage(texImageTarget, uHostMipmap, pSurface->formatGL, pSurface->typeGL, pDoubleBuffer);
2963 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2964 }
2965
2966 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
2967
2968 /* Restore the old active texture. */
2969 glBindTexture(pSurface->targetGL, activeTexture);
2970 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
2971
2972 offHst = u32HostBlockX * pSurface->cbBlock + u32HostBlockY * pMipLevel->cbSurfacePitch + u32HostZ * pMipLevel->cbSurfacePlane;
2973 cbSurfacePitch = pMipLevel->cbSurfacePitch;
2974 }
2975 else
2976 {
2977 /* The buffer will contain only the copied rectangle. */
2978 offHst = 0;
2979 cbSurfacePitch = cBlocksX * pSurface->cbBlock;
2980 }
2981
2982 uint64_t offGst = u32GuestBlockX * pSurface->cbBlock + u32GuestBlockY * cbGuestPitch + u32GuestZ * cbGuestPitch * pMipLevel->mipmapSize.height;
2983
2984 for (uint32_t iPlane = 0; iPlane < pBox->d; ++iPlane)
2985 {
2986 AssertBreak(offHst < UINT32_MAX);
2987 AssertBreak(offGst < UINT32_MAX);
2988
2989 rc = vmsvgaR3GmrTransfer(pThis,
2990 pThisCC,
2991 transfer,
2992 pDoubleBuffer,
2993 pMipLevel->cbSurface,
2994 (uint32_t)offHst,
2995 cbSurfacePitch,
2996 GuestPtr,
2997 (uint32_t)offGst,
2998 cbGuestPitch,
2999 cBlocksX * pSurface->cbBlock,
3000 cBlocksY);
3001 AssertRC(rc);
3002
3003 offHst += pMipLevel->cbSurfacePlane;
3004 offGst += pMipLevel->mipmapSize.height * cbGuestPitch;
3005 }
3006
3007 /* Update the opengl surface data. */
3008 if (transfer == SVGA3D_WRITE_HOST_VRAM)
3009 {
3010 GLint activeTexture = 0;
3011 glGetIntegerv(pSurface->bindingGL, &activeTexture);
3012 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3013
3014 /* Must bind texture to the current context in order to change it. */
3015 glBindTexture(pSurface->targetGL, GLTextureId(pSurface));
3016 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3017
3018 LogFunc(("copy texture mipmap level %d (pitch %x)\n", uHostMipmap, pMipLevel->cbSurfacePitch));
3019
3020 /* Set row length and alignment of the input data. */
3021 /* We do not need to set ROW_LENGTH to w here, because the image in pDoubleBuffer is tightly packed. */
3022 VMSVGAPACKPARAMS SavedParams;
3023 vmsvga3dOglSetUnpackParams(pState, pContext, 0, 0, &SavedParams);
3024
3025 if (texImageTarget == GL_TEXTURE_3D)
3026 {
3027 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
3028 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
3029 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
3030 {
3031 pState->ext.glCompressedTexSubImage3D(texImageTarget,
3032 uHostMipmap,
3033 pBox->x,
3034 pBox->y,
3035 pBox->z,
3036 pBox->w,
3037 pBox->h,
3038 pBox->d,
3039 pSurface->internalFormatGL,
3040 cbSurfacePitch * cBlocksY * pBox->d,
3041 pDoubleBuffer);
3042 }
3043 else
3044 {
3045 pState->ext.glTexSubImage3D(texImageTarget,
3046 uHostMipmap,
3047 u32HostBlockX,
3048 u32HostBlockY,
3049 pBox->z,
3050 cBlocksX,
3051 cBlocksY,
3052 pBox->d,
3053 pSurface->formatGL,
3054 pSurface->typeGL,
3055 pDoubleBuffer);
3056 }
3057 }
3058 else
3059 {
3060 if ( pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
3061 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
3062 || pSurface->internalFormatGL == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
3063 {
3064 pState->ext.glCompressedTexSubImage2D(texImageTarget,
3065 uHostMipmap,
3066 pBox->x,
3067 pBox->y,
3068 pBox->w,
3069 pBox->h,
3070 pSurface->internalFormatGL,
3071 cbSurfacePitch * cBlocksY,
3072 pDoubleBuffer);
3073 }
3074 else
3075 {
3076 glTexSubImage2D(texImageTarget,
3077 uHostMipmap,
3078 u32HostBlockX,
3079 u32HostBlockY,
3080 cBlocksX,
3081 cBlocksY,
3082 pSurface->formatGL,
3083 pSurface->typeGL,
3084 pDoubleBuffer);
3085 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3086
3087 if (pSurface->fEmulated)
3088 {
3089 /* Convert the texture to the actual texture if necessary */
3090 FormatConvUpdateTexture(pState, pContext, pSurface, uHostMipmap);
3091 }
3092 }
3093 }
3094 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3095
3096 /* Restore old values. */
3097 vmsvga3dOglRestoreUnpackParams(pState, pContext, &SavedParams);
3098
3099 /* Restore the old active texture. */
3100 glBindTexture(pSurface->targetGL, activeTexture);
3101 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
3102 }
3103
3104 Log4(("first line:\n%.*Rhxd\n", cBlocksX * pSurface->cbBlock, pDoubleBuffer));
3105
3106 /* Free the double buffer. */
3107 RTMemFree(pDoubleBuffer);
3108 break;
3109 }
3110
3111 case VMSVGA3D_OGLRESTYPE_BUFFER:
3112 {
3113 /* Buffers are uncompressed. */
3114 AssertReturn(pSurface->cxBlock == 1 && pSurface->cyBlock == 1, VERR_INTERNAL_ERROR);
3115
3116 /* Caller already clipped pBox and buffers are 1-dimensional. */
3117 Assert(pBox->y == 0 && pBox->h == 1 && pBox->z == 0 && pBox->d == 1);
3118
3119 VMSVGA3D_CLEAR_GL_ERRORS();
3120 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
3121 if (VMSVGA3D_GL_IS_SUCCESS(pContext))
3122 {
3123 GLenum enmGlTransfer = (transfer == SVGA3D_READ_HOST_VRAM) ? GL_READ_ONLY : GL_WRITE_ONLY;
3124 uint8_t *pbData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, enmGlTransfer);
3125 if (RT_LIKELY(pbData != NULL))
3126 {
3127#if defined(VBOX_STRICT) && defined(RT_OS_DARWIN)
3128 GLint cbStrictBufSize;
3129 glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &cbStrictBufSize);
3130 Assert(VMSVGA3D_GL_IS_SUCCESS(pContext));
3131 AssertMsg(cbStrictBufSize >= (int32_t)pMipLevel->cbSurface,
3132 ("cbStrictBufSize=%#x cbSurface=%#x pContext->id=%#x\n", (uint32_t)cbStrictBufSize, pMipLevel->cbSurface, pContext->id));
3133#endif
3134 Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n",
3135 (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_VERTEXBUFFER ? "vertex" :
3136 (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK) == SVGA3D_SURFACE_HINT_INDEXBUFFER ? "index" : "buffer",
3137 pBox->x, pBox->y, pBox->x + pBox->w, pBox->y + pBox->h));
3138
3139 /* The caller already copied the data to the pMipLevel->pSurfaceData buffer, see VMSVGA3DSURFACE_NEEDS_DATA. */
3140 uint32_t const offHst = pBox->x * pSurface->cbBlock;
3141 uint32_t const cbWidth = pBox->w * pSurface->cbBlock;
3142
3143 memcpy(pbData + offHst, (uint8_t *)pMipLevel->pSurfaceData + offHst, cbWidth);
3144
3145 Log4(("Buffer updated at [0x%x;0x%x):\n%.*Rhxd\n", offHst, offHst + cbWidth, cbWidth, (uint8_t *)pbData + offHst));
3146
3147 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
3148 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3149 }
3150 else
3151 VMSVGA3D_GL_GET_AND_COMPLAIN(pState, pContext, ("glMapBuffer(GL_ARRAY_BUFFER, %#x) -> NULL\n", enmGlTransfer));
3152 }
3153 else
3154 VMSVGA3D_GL_COMPLAIN(pState, pContext, ("glBindBuffer(GL_ARRAY_BUFFER, %#x)\n", pSurface->oglId.buffer));
3155 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
3156 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3157 break;
3158 }
3159
3160 default:
3161 AssertFailed();
3162 break;
3163 }
3164
3165 return rc;
3166}
3167
3168static DECLCALLBACK(int) vmsvga3dBackGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter)
3169{
3170 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3171 PVMSVGA3DSURFACE pSurface;
3172 int rc = VINF_SUCCESS;
3173 PVMSVGA3DCONTEXT pContext;
3174 uint32_t cid;
3175 GLint activeTexture = 0;
3176
3177 AssertReturn(pState, VERR_NO_MEMORY);
3178
3179 rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
3180 AssertRCReturn(rc, rc);
3181
3182 Assert(filter != SVGA3D_TEX_FILTER_FLATCUBIC);
3183 Assert(filter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
3184 pSurface->autogenFilter = filter;
3185
3186 LogFunc(("sid=%u filter=%d\n", sid, filter));
3187
3188 cid = SVGA3D_INVALID_ID;
3189 pContext = &pState->SharedCtx;
3190 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
3191
3192 if (pSurface->oglId.texture == OPENGL_INVALID_ID)
3193 {
3194 /* Unknown surface type; turn it into a texture. */
3195 LogFunc(("unknown src surface id=%x type=%d format=%d -> create texture\n", sid, pSurface->surfaceFlags, pSurface->format));
3196 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface);
3197 AssertRCReturn(rc, rc);
3198 }
3199 else
3200 {
3201 /** @todo new filter */
3202 AssertFailed();
3203 }
3204
3205 glGetIntegerv(pSurface->bindingGL, &activeTexture);
3206 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3207
3208 /* Must bind texture to the current context in order to change it. */
3209 glBindTexture(pSurface->targetGL, pSurface->oglId.texture);
3210 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3211
3212 /* Generate the mip maps. */
3213 pState->ext.glGenerateMipmap(pSurface->targetGL);
3214 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3215
3216 /* Restore the old texture. */
3217 glBindTexture(pSurface->targetGL, activeTexture);
3218 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3219
3220 return VINF_SUCCESS;
3221}
3222
3223
3224#ifdef RT_OS_LINUX
3225/**
3226 * X11 event handling thread.
3227 *
3228 * @returns VINF_SUCCESS (ignored)
3229 * @param hThreadSelf thread handle
3230 * @param pvUser pointer to pState structure
3231 */
3232DECLCALLBACK(int) vmsvga3dXEventThread(RTTHREAD hThreadSelf, void *pvUser)
3233{
3234 RT_NOREF(hThreadSelf);
3235 PVMSVGA3DSTATE pState = (PVMSVGA3DSTATE)pvUser;
3236 while (!pState->bTerminate)
3237 {
3238 while (XPending(pState->display) > 0)
3239 {
3240 XEvent event;
3241 XNextEvent(pState->display, &event);
3242
3243 switch (event.type)
3244 {
3245 default:
3246 break;
3247 }
3248 }
3249 /* sleep for 16ms to not burn too many cycles */
3250 RTThreadSleep(16);
3251 }
3252 return VINF_SUCCESS;
3253}
3254#endif // RT_OS_LINUX
3255
3256
3257/**
3258 * Create a new 3d context
3259 *
3260 * @returns VBox status code.
3261 * @param pThisCC The VGA/VMSVGA state for ring-3.
3262 * @param cid Context id
3263 * @param fFlags VMSVGA3D_DEF_CTX_F_XXX.
3264 */
3265int vmsvga3dContextDefineOgl(PVGASTATECC pThisCC, uint32_t cid, uint32_t fFlags)
3266{
3267 int rc;
3268 PVMSVGA3DCONTEXT pContext;
3269 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3270
3271 AssertReturn(pState, VERR_NO_MEMORY);
3272 AssertReturn( cid < SVGA3D_MAX_CONTEXT_IDS
3273 || (cid == VMSVGA3D_SHARED_CTX_ID && (fFlags & VMSVGA3D_DEF_CTX_F_SHARED_CTX)), VERR_INVALID_PARAMETER);
3274#if !defined(VBOX_VMSVGA3D_DUAL_OPENGL_PROFILE) || !(defined(RT_OS_DARWIN))
3275 AssertReturn(!(fFlags & VMSVGA3D_DEF_CTX_F_OTHER_PROFILE), VERR_INTERNAL_ERROR_3);
3276#endif
3277
3278 Log(("vmsvga3dContextDefine id %x\n", cid));
3279
3280 if (cid == VMSVGA3D_SHARED_CTX_ID)
3281 pContext = &pState->SharedCtx;
3282 else
3283 {
3284 if (cid >= pState->cContexts)
3285 {
3286 /* Grow the array. */
3287 uint32_t cNew = RT_ALIGN(cid + 15, 16);
3288 void *pvNew = RTMemRealloc(pState->papContexts, sizeof(pState->papContexts[0]) * cNew);
3289 AssertReturn(pvNew, VERR_NO_MEMORY);
3290 pState->papContexts = (PVMSVGA3DCONTEXT *)pvNew;
3291 while (pState->cContexts < cNew)
3292 {
3293 pContext = (PVMSVGA3DCONTEXT)RTMemAllocZ(sizeof(*pContext));
3294 AssertReturn(pContext, VERR_NO_MEMORY);
3295 pContext->id = SVGA3D_INVALID_ID;
3296 pState->papContexts[pState->cContexts++] = pContext;
3297 }
3298 }
3299 /* If one already exists with this id, then destroy it now. */
3300 if (pState->papContexts[cid]->id != SVGA3D_INVALID_ID)
3301 vmsvga3dBackContextDestroy(pThisCC, cid);
3302
3303 pContext = pState->papContexts[cid];
3304 }
3305
3306 /*
3307 * Find or create the shared context if needed (necessary for sharing e.g. textures between contexts).
3308 */
3309 PVMSVGA3DCONTEXT pSharedCtx = NULL;
3310 if (!(fFlags & (VMSVGA3D_DEF_CTX_F_INIT | VMSVGA3D_DEF_CTX_F_SHARED_CTX)))
3311 {
3312 pSharedCtx = &pState->SharedCtx;
3313 if (pSharedCtx->id != VMSVGA3D_SHARED_CTX_ID)
3314 {
3315 rc = vmsvga3dContextDefineOgl(pThisCC, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX);
3316 AssertLogRelRCReturn(rc, rc);
3317
3318 /* Create resources which use the shared context. */
3319 vmsvga3dOnSharedContextDefine(pState);
3320 }
3321 }
3322
3323 /*
3324 * Initialize the context.
3325 */
3326 memset(pContext, 0, sizeof(*pContext));
3327 pContext->id = cid;
3328 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); i++)
3329 pContext->aSidActiveTextures[i] = SVGA3D_INVALID_ID;
3330
3331 pContext->state.shidVertex = SVGA3D_INVALID_ID;
3332 pContext->state.shidPixel = SVGA3D_INVALID_ID;
3333 pContext->idFramebuffer = OPENGL_INVALID_ID;
3334 pContext->idReadFramebuffer = OPENGL_INVALID_ID;
3335 pContext->idDrawFramebuffer = OPENGL_INVALID_ID;
3336
3337 rc = ShaderContextCreate(&pContext->pShaderContext);
3338 AssertRCReturn(rc, rc);
3339
3340 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); i++)
3341 pContext->state.aRenderTargets[i] = SVGA3D_INVALID_ID;
3342
3343#ifdef RT_OS_WINDOWS
3344 /* Create a context window with minimal 4x4 size. We will never use the swapchain
3345 * to present the rendered image. Rendered images from the guest will be copied to
3346 * the VMSVGA SCREEN object, which can be either an offscreen render target or
3347 * system memory in the guest VRAM.
3348 */
3349 rc = vmsvga3dContextWindowCreate(pState->hInstance, pState->pWindowThread, pState->WndRequestSem, &pContext->hwnd);
3350 AssertRCReturn(rc, rc);
3351
3352 pContext->hdc = GetDC(pContext->hwnd);
3353 AssertMsgReturn(pContext->hdc, ("GetDC %x failed with %d\n", pContext->hwnd, GetLastError()), VERR_INTERNAL_ERROR);
3354
3355 PIXELFORMATDESCRIPTOR pfd = {
3356 sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
3357 1, /* version number */
3358 PFD_DRAW_TO_WINDOW | /* support window */
3359 PFD_SUPPORT_OPENGL, /* support OpenGL */
3360 PFD_TYPE_RGBA, /* RGBA type */
3361 24, /* 24-bit color depth */
3362 0, 0, 0, 0, 0, 0, /* color bits ignored */
3363 8, /* alpha buffer */
3364 0, /* shift bit ignored */
3365 0, /* no accumulation buffer */
3366 0, 0, 0, 0, /* accum bits ignored */
3367 16, /* set depth buffer */
3368 16, /* set stencil buffer */
3369 0, /* no auxiliary buffer */
3370 PFD_MAIN_PLANE, /* main layer */
3371 0, /* reserved */
3372 0, 0, 0 /* layer masks ignored */
3373 };
3374 int pixelFormat;
3375 BOOL ret;
3376
3377 pixelFormat = ChoosePixelFormat(pContext->hdc, &pfd);
3378 /** @todo is this really necessary?? */
3379 pixelFormat = ChoosePixelFormat(pContext->hdc, &pfd);
3380 AssertMsgReturn(pixelFormat != 0, ("ChoosePixelFormat failed with %d\n", GetLastError()), VERR_INTERNAL_ERROR);
3381
3382 ret = SetPixelFormat(pContext->hdc, pixelFormat, &pfd);
3383 AssertMsgReturn(ret == TRUE, ("SetPixelFormat failed with %d\n", GetLastError()), VERR_INTERNAL_ERROR);
3384
3385 pContext->hglrc = wglCreateContext(pContext->hdc);
3386 AssertMsgReturn(pContext->hglrc, ("wglCreateContext %x failed with %d\n", pContext->hdc, GetLastError()), VERR_INTERNAL_ERROR);
3387
3388 if (pSharedCtx)
3389 {
3390 ret = wglShareLists(pSharedCtx->hglrc, pContext->hglrc);
3391 AssertMsg(ret == TRUE, ("wglShareLists(%p, %p) failed with %d\n", pSharedCtx->hglrc, pContext->hglrc, GetLastError()));
3392 }
3393
3394#elif defined(RT_OS_DARWIN)
3395 pContext->fOtherProfile = RT_BOOL(fFlags & VMSVGA3D_DEF_CTX_F_OTHER_PROFILE);
3396
3397 NativeNSOpenGLContextRef pShareContext = pSharedCtx ? pSharedCtx->cocoaContext : NULL;
3398 vmsvga3dCocoaCreateViewAndContext(&pContext->cocoaView, &pContext->cocoaContext,
3399 NULL,
3400 4, 4,
3401 pShareContext, pContext->fOtherProfile);
3402
3403#else
3404 if (pState->display == NULL)
3405 {
3406 /* get an X display and make sure we have glX 1.3 */
3407 pState->display = XOpenDisplay(0);
3408 AssertLogRelMsgReturn(pState->display, ("XOpenDisplay failed"), VERR_INTERNAL_ERROR);
3409 int glxMajor, glxMinor;
3410 Bool ret = glXQueryVersion(pState->display, &glxMajor, &glxMinor);
3411 AssertLogRelMsgReturn(ret && glxMajor == 1 && glxMinor >= 3, ("glX >=1.3 not present"), VERR_INTERNAL_ERROR);
3412 /* start our X event handling thread */
3413 rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dXEventThread, pState, 0, RTTHREADTYPE_GUI, RTTHREADFLAGS_WAITABLE, "VMSVGA3DXEVENT");
3414 AssertLogRelMsgReturn(RT_SUCCESS(rc), ("Async IO Thread creation for 3d window handling failed rc=%Rrc\n", rc), rc);
3415 }
3416
3417 Window defaultRootWindow = XDefaultRootWindow(pState->display);
3418 /* Create a small 4x4 window required for GL context. */
3419 int attrib[] =
3420 {
3421 GLX_RGBA,
3422 GLX_RED_SIZE, 1,
3423 GLX_GREEN_SIZE, 1,
3424 GLX_BLUE_SIZE, 1,
3425 //GLX_ALPHA_SIZE, 1, this flips the bbos screen
3426 GLX_DOUBLEBUFFER,
3427 None
3428 };
3429 XVisualInfo *vi = glXChooseVisual(pState->display, DefaultScreen(pState->display), attrib);
3430 AssertLogRelMsgReturn(vi, ("glXChooseVisual failed"), VERR_INTERNAL_ERROR);
3431 XSetWindowAttributes swa;
3432 swa.colormap = XCreateColormap(pState->display, defaultRootWindow, vi->visual, AllocNone);
3433 AssertLogRelMsgReturn(swa.colormap, ("XCreateColormap failed"), VERR_INTERNAL_ERROR);
3434 swa.border_pixel = 0;
3435 swa.background_pixel = 0;
3436 swa.event_mask = StructureNotifyMask;
3437 unsigned long flags = CWBorderPixel | CWBackPixel | CWColormap | CWEventMask;
3438 pContext->window = XCreateWindow(pState->display, defaultRootWindow,
3439 0, 0, 4, 4,
3440 0, vi->depth, InputOutput,
3441 vi->visual, flags, &swa);
3442 AssertLogRelMsgReturn(pContext->window, ("XCreateWindow failed"), VERR_INTERNAL_ERROR);
3443
3444 /* The window is hidden by default and never mapped, because we only render offscreen and never present to it. */
3445
3446 GLXContext shareContext = pSharedCtx ? pSharedCtx->glxContext : NULL;
3447 pContext->glxContext = glXCreateContext(pState->display, vi, shareContext, GL_TRUE);
3448 AssertLogRelMsgReturn(pContext->glxContext, ("glXCreateContext failed"), VERR_INTERNAL_ERROR);
3449#endif
3450
3451 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
3452
3453 /* NULL during the first PowerOn call. */
3454 if (pState->ext.glGenFramebuffers)
3455 {
3456 /* Create a framebuffer object for this context. */
3457 pState->ext.glGenFramebuffers(1, &pContext->idFramebuffer);
3458 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3459
3460 /* Bind the object to the framebuffer target. */
3461 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, pContext->idFramebuffer);
3462 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3463
3464 /* Create read and draw framebuffer objects for this context. */
3465 pState->ext.glGenFramebuffers(1, &pContext->idReadFramebuffer);
3466 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3467
3468 pState->ext.glGenFramebuffers(1, &pContext->idDrawFramebuffer);
3469 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
3470
3471 }
3472#if 0
3473 /** @todo move to shader lib!!! */
3474 /* Clear the screen */
3475 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
3476
3477 glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
3478 glClearIndex(0);
3479 glClearDepth(1);
3480 glClearStencil(0xffff);
3481 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
3482 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
3483 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
3484 if (pState->ext.glProvokingVertex)
3485 pState->ext.glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
3486 /** @todo move to shader lib!!! */
3487#endif
3488 return VINF_SUCCESS;
3489}
3490
3491#if defined(RT_OS_LINUX)
3492/*
3493 * HW accelerated graphics output.
3494 */
3495
3496/**
3497 * VMSVGA3d screen data.
3498 *
3499 * Allocated on the heap and pointed to by VMSVGASCREENOBJECT::pHwScreen.
3500 */
3501typedef struct VMSVGAHWSCREEN
3502{
3503 /* OpenGL context, which is used for the screen updates. */
3504 GLXContext glxctx;
3505
3506 /* The overlay window. */
3507 Window xwindow;
3508
3509 /* The RGBA texture which hold the screen content. */
3510 GLuint idScreenTexture;
3511
3512 /* Read and draw framebuffer objects for copying a surface to the screen texture. */
3513 GLuint idReadFramebuffer;
3514 GLuint idDrawFramebuffer;
3515} VMSVGAHWSCREEN;
3516
3517/* Send a notification to the UI. */
3518#if 0 /* Unused */
3519static int vmsvga3dDrvNotifyHwScreen(PVGASTATECC pThisCC, VBOX3D_NOTIFY_TYPE enmNotification,
3520 uint32_t idScreen, Pixmap pixmap, void *pvData, size_t cbData)
3521{
3522 uint8_t au8Buffer[128];
3523 AssertLogRelMsgReturn(cbData <= sizeof(au8Buffer) - sizeof(VBOX3DNOTIFY),
3524 ("cbData %zu", cbData),
3525 VERR_INVALID_PARAMETER);
3526
3527 VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0];
3528 p->enmNotification = enmNotification;
3529 p->iDisplay = idScreen;
3530 p->u32Reserved = 0;
3531 p->cbData = cbData + sizeof(uint64_t);
3532 /* au8Data consists of a 64 bit pixmap handle followed by notification specific data. */
3533 AssertCompile(sizeof(pixmap) <= sizeof(uint64_t));
3534 *(uint64_t *)&p->au8Data[0] = (uint64_t)pixmap;
3535 memcpy(&p->au8Data[sizeof(uint64_t)], pvData, cbData);
3536
3537 int rc = pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p);
3538 return rc;
3539}
3540#endif /* Unused */
3541
3542static void vmsvga3dDrvNotifyHwOverlay(PVGASTATECC pThisCC, VBOX3D_NOTIFY_TYPE enmNotification, uint32_t idScreen)
3543{
3544 uint8_t au8Buffer[128];
3545 VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0];
3546 p->enmNotification = enmNotification;
3547 p->iDisplay = idScreen;
3548 p->u32Reserved = 0;
3549 p->cbData = sizeof(uint64_t);
3550 *(uint64_t *)&p->au8Data[0] = 0;
3551
3552 pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p);
3553}
3554
3555/* Get X Window handle of the UI Framebuffer window. */
3556static int vmsvga3dDrvQueryWindow(PVGASTATECC pThisCC, uint32_t idScreen, Window *pWindow)
3557{
3558 uint8_t au8Buffer[128];
3559 VBOX3DNOTIFY *p = (VBOX3DNOTIFY *)&au8Buffer[0];
3560 p->enmNotification = VBOX3D_NOTIFY_TYPE_HW_OVERLAY_GET_ID;
3561 p->iDisplay = idScreen;
3562 p->u32Reserved = 0;
3563 p->cbData = sizeof(uint64_t);
3564 *(uint64_t *)&p->au8Data[0] = 0;
3565
3566 int rc = pThisCC->pDrv->pfn3DNotifyProcess(pThisCC->pDrv, p);
3567 if (RT_SUCCESS(rc))
3568 {
3569 *pWindow = (Window)*(uint64_t *)&p->au8Data[0];
3570 }
3571 return rc;
3572}
3573
3574static int ctxErrorHandler(Display *dpy, XErrorEvent *ev)
3575{
3576 RT_NOREF(dpy);
3577 LogRel4(("VMSVGA: XError %d\n", (int)ev->error_code));
3578 return 0;
3579}
3580
3581/* Create an overlay X window for the HW accelerated screen. */
3582static int vmsvga3dHwScreenCreate(PVMSVGA3DSTATE pState, Window parentWindow, unsigned int cWidth, unsigned int cHeight, VMSVGAHWSCREEN *p)
3583{
3584 int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
3585
3586 int rc = VINF_SUCCESS;
3587
3588 XWindowAttributes parentAttr;
3589 if (XGetWindowAttributes(pState->display, parentWindow, &parentAttr) == 0)
3590 return VERR_INVALID_PARAMETER;
3591
3592 int const idxParentScreen = XScreenNumberOfScreen(parentAttr.screen);
3593
3594 /*
3595 * Create a new GL context, which will be used for copying to the screen.
3596 */
3597
3598 /* FBConfig attributes for the overlay window. */
3599 static int const aConfigAttribList[] =
3600 {
3601 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, // Must support GLX windows
3602 GLX_DOUBLEBUFFER, False, // Double buffering had a much lower performance.
3603 GLX_RED_SIZE, 8, // True color RGB with 8 bits per channel.
3604 GLX_GREEN_SIZE, 8,
3605 GLX_BLUE_SIZE, 8,
3606 GLX_ALPHA_SIZE, 8,
3607 GLX_STENCIL_SIZE, 0, // No stencil buffer
3608 GLX_DEPTH_SIZE, 0, // No depth buffer
3609 None
3610 };
3611
3612 /* Find a suitable FB config. */
3613 int cConfigs = 0;
3614 GLXFBConfig *paConfigs = glXChooseFBConfig(pState->display, idxParentScreen, aConfigAttribList, &cConfigs);
3615 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: paConfigs %p cConfigs %d\n", (void *)paConfigs, cConfigs));
3616 if (paConfigs)
3617 {
3618 XVisualInfo *vi = NULL;
3619 int i = 0;
3620 for (; i < cConfigs; ++i)
3621 {
3622 /* Use XFree to free the data returned in the previous iteration of this loop. */
3623 if (vi)
3624 XFree(vi);
3625
3626 vi = glXGetVisualFromFBConfig(pState->display, paConfigs[i]);
3627 if (!vi)
3628 continue;
3629
3630 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: %p vid %lu screen %d depth %d r %lu g %lu b %lu clrmap %d bitsperrgb %d\n",
3631 (void *)vi->visual, vi->visualid, vi->screen, vi->depth,
3632 vi->red_mask, vi->green_mask, vi->blue_mask, vi->colormap_size, vi->bits_per_rgb));
3633
3634 /* Same screen as the parent window. */
3635 if (vi->screen != idxParentScreen)
3636 continue;
3637
3638 /* Search for 32 bits per pixel. */
3639 if (vi->depth != 32)
3640 continue;
3641
3642 /* 8 bits per color component is enough. */
3643 if (vi->bits_per_rgb != 8)
3644 continue;
3645
3646 /* Render to pixmap. */
3647 int value = 0;
3648 glXGetFBConfigAttrib(pState->display, paConfigs[i], GLX_DRAWABLE_TYPE, &value);
3649 if (!(value & GLX_WINDOW_BIT))
3650 continue;
3651
3652 /* This FB config can be used. */
3653 break;
3654 }
3655
3656 if (i < cConfigs)
3657 {
3658 /* Found a suitable config with index i. */
3659
3660 /* Create an overlay window. */
3661 XSetWindowAttributes swa;
3662 RT_ZERO(swa);
3663
3664 swa.colormap = XCreateColormap(pState->display, parentWindow, vi->visual, AllocNone);
3665 AssertLogRelMsg(swa.colormap, ("XCreateColormap failed"));
3666 swa.border_pixel = 0;
3667 swa.background_pixel = 0;
3668 swa.event_mask = StructureNotifyMask;
3669 swa.override_redirect = 1;
3670 unsigned long const swaAttrs = CWBorderPixel | CWBackPixel | CWColormap | CWEventMask | CWOverrideRedirect;
3671 p->xwindow = XCreateWindow(pState->display, parentWindow,
3672 0, 0, cWidth, cHeight, 0, vi->depth, InputOutput,
3673 vi->visual, swaAttrs, &swa);
3674 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: p->xwindow %ld\n", p->xwindow));
3675 if (p->xwindow)
3676 {
3677
3678 p->glxctx = glXCreateContext(pState->display, vi, pState->SharedCtx.glxContext, GL_TRUE);
3679 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: p->glxctx %p\n", (void *)p->glxctx));
3680 if (p->glxctx)
3681 {
3682 XMapWindow(pState->display, p->xwindow);
3683 }
3684 else
3685 {
3686 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: glXCreateContext failed\n"));
3687 rc = VERR_NOT_SUPPORTED;
3688 }
3689 }
3690 else
3691 {
3692 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: XCreateWindow failed\n"));
3693 rc = VERR_NOT_SUPPORTED;
3694 }
3695
3696 XSync(pState->display, False);
3697 }
3698 else
3699 {
3700 /* A suitable config is not found. */
3701 LogRel4(("VMSVGA: vmsvga3dHwScreenCreate: no FBConfig\n"));
3702 rc = VERR_NOT_SUPPORTED;
3703 }
3704
3705 if (vi)
3706 XFree(vi);
3707
3708 /* "Use XFree to free the memory returned by glXChooseFBConfig." */
3709 XFree(paConfigs);
3710 }
3711 else
3712 {
3713 /* glXChooseFBConfig failed. */
3714 rc = VERR_NOT_SUPPORTED;
3715 }
3716
3717 XSetErrorHandler(oldHandler);
3718 return rc;
3719}
3720
3721/* Destroy a HW accelerated screen. */
3722static void vmsvga3dHwScreenDestroy(PVMSVGA3DSTATE pState, VMSVGAHWSCREEN *p)
3723{
3724 if (p)
3725 {
3726 LogRel4(("VMSVGA: vmsvga3dHwScreenDestroy: p->xwindow %ld, ctx %p\n", p->xwindow, (void *)p->glxctx));
3727 if (p->glxctx)
3728 {
3729 /* GLX context is changed here, so other code has to set the appropriate context again. */
3730 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
3731
3732 glXMakeCurrent(pState->display, p->xwindow, p->glxctx);
3733
3734 /* Clean up OpenGL. */
3735 if (p->idReadFramebuffer != OPENGL_INVALID_ID)
3736 pState->ext.glDeleteFramebuffers(1, &p->idReadFramebuffer);
3737 if (p->idDrawFramebuffer != OPENGL_INVALID_ID)
3738 pState->ext.glDeleteFramebuffers(1, &p->idDrawFramebuffer);
3739 if (p->idScreenTexture != OPENGL_INVALID_ID)
3740 glDeleteTextures(1, &p->idScreenTexture);
3741
3742 glXMakeCurrent(pState->display, None, NULL);
3743
3744 glXDestroyContext(pState->display, p->glxctx);
3745 }
3746
3747 if (p->xwindow)
3748 XDestroyWindow(pState->display, p->xwindow);
3749
3750 RT_ZERO(*p);
3751 }
3752}
3753
3754#define GLCHECK() \
3755 do { \
3756 int glErr = glGetError(); \
3757 if (glErr != GL_NO_ERROR) LogRel4(("VMSVGA: GL error 0x%x @%d\n", glErr, __LINE__)); \
3758 } while(0)
3759
3760static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3761{
3762 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: screen %u\n", pScreen->idScreen));
3763
3764 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3765 AssertReturn(pState, VERR_NOT_SUPPORTED);
3766
3767 if (!pThis->svga.f3DOverlayEnabled)
3768 return VERR_NOT_SUPPORTED;
3769
3770 Assert(pScreen->pHwScreen == NULL);
3771
3772 VMSVGAHWSCREEN *p = (VMSVGAHWSCREEN *)RTMemAllocZ(sizeof(VMSVGAHWSCREEN));
3773 AssertPtrReturn(p, VERR_NO_MEMORY);
3774
3775 /* Query the parent window ID from the UI framebuffer.
3776 * If it is there then
3777 * the device will create a texture for the screen content and an overlay window to present the screen content.
3778 * otherwise
3779 * the device will use the guest VRAM system memory for the screen content.
3780 */
3781 Window parentWindow;
3782 int rc = vmsvga3dDrvQueryWindow(pThisCC, pScreen->idScreen, &parentWindow);
3783 if (RT_SUCCESS(rc))
3784 {
3785 /* Create the hardware accelerated screen. */
3786 rc = vmsvga3dHwScreenCreate(pState, parentWindow, pScreen->cWidth, pScreen->cHeight, p);
3787 if (RT_SUCCESS(rc))
3788 {
3789 /*
3790 * Setup the OpenGL context of the screen. The context will be used to draw on the screen.
3791 */
3792
3793 /* GLX context is changed here, so other code has to set the appropriate context again. */
3794 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
3795
3796 Bool const fSuccess = glXMakeCurrent(pState->display, p->xwindow, p->glxctx);
3797 if (fSuccess)
3798 {
3799 /* Set GL state. */
3800 glClearColor(0, 0, 0, 1);
3801 glEnable(GL_TEXTURE_2D);
3802 glDisable(GL_DEPTH_TEST);
3803 glDisable(GL_CULL_FACE);
3804
3805 /* The RGBA texture which hold the screen content. */
3806 glGenTextures(1, &p->idScreenTexture); GLCHECK();
3807 glBindTexture(GL_TEXTURE_2D, p->idScreenTexture); GLCHECK();
3808 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); GLCHECK();
3809 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); GLCHECK();
3810 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, pScreen->cWidth, pScreen->cHeight, 0,
3811 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); GLCHECK();
3812
3813 /* Create read and draw framebuffer objects for this screen. */
3814 pState->ext.glGenFramebuffers(1, &p->idReadFramebuffer); GLCHECK();
3815 pState->ext.glGenFramebuffers(1, &p->idDrawFramebuffer); GLCHECK();
3816
3817 /* Work in screen coordinates. */
3818 glMatrixMode(GL_MODELVIEW);
3819 glLoadIdentity();
3820 glOrtho(0, pScreen->cWidth, 0, pScreen->cHeight, -1, 1);
3821 glMatrixMode(GL_PROJECTION);
3822 glLoadIdentity();
3823
3824 /* Clear the texture. */
3825 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p->idDrawFramebuffer); GLCHECK();
3826 pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3827 p->idScreenTexture, 0); GLCHECK();
3828
3829 glClear(GL_COLOR_BUFFER_BIT);
3830
3831 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); GLCHECK();
3832
3833 glXMakeCurrent(pState->display, None, NULL);
3834
3835 XSync(pState->display, False);
3836
3837 vmsvga3dDrvNotifyHwOverlay(pThisCC, VBOX3D_NOTIFY_TYPE_HW_OVERLAY_CREATED, pScreen->idScreen);
3838 }
3839 else
3840 {
3841 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: failed to set current context\n"));
3842 rc = VERR_NOT_SUPPORTED;
3843 }
3844 }
3845 }
3846 else
3847 {
3848 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: no framebuffer\n"));
3849 }
3850
3851 if (RT_SUCCESS(rc))
3852 {
3853 LogRel(("VMSVGA: Using HW accelerated screen %u\n", pScreen->idScreen));
3854 pScreen->pHwScreen = p;
3855 }
3856 else
3857 {
3858 LogRel4(("VMSVGA: vmsvga3dBackDefineScreen: %Rrc\n", rc));
3859 vmsvga3dHwScreenDestroy(pState, p);
3860 RTMemFree(p);
3861 }
3862
3863 return rc;
3864}
3865
3866static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3867{
3868 LogRel4(("VMSVGA: vmsvga3dBackDestroyScreen: screen %u\n", pScreen->idScreen));
3869
3870 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3871 AssertReturn(pState, VERR_NOT_SUPPORTED);
3872
3873 int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
3874
3875 VMSVGAHWSCREEN *p = pScreen->pHwScreen;
3876 if (p)
3877 {
3878 pScreen->pHwScreen = NULL;
3879
3880 vmsvga3dDrvNotifyHwOverlay(pThisCC, VBOX3D_NOTIFY_TYPE_HW_OVERLAY_DESTROYED, pScreen->idScreen);
3881
3882 vmsvga3dHwScreenDestroy(pState, p);
3883 RTMemFree(p);
3884 }
3885
3886 XSetErrorHandler(oldHandler);
3887
3888 return VINF_SUCCESS;
3889}
3890
3891/* Blit a surface to the GLX pixmap. */
3892static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen,
3893 SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage,
3894 SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects)
3895{
3896 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
3897 AssertReturn(pState, VERR_NOT_SUPPORTED);
3898
3899 VMSVGAHWSCREEN *p = pScreen->pHwScreen;
3900 AssertReturn(p, VERR_NOT_SUPPORTED);
3901
3902 PVMSVGA3DSURFACE pSurface;
3903 int rc = vmsvga3dSurfaceFromSid(pState, srcImage.sid, &pSurface);
3904 AssertRCReturn(rc, rc);
3905
3906 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
3907 {
3908 LogFunc(("src sid=%u flags=0x%x format=%d -> create texture\n", srcImage.sid, pSurface->surfaceFlags, pSurface->format));
3909 rc = vmsvga3dBackCreateTexture(pThisCC, &pState->SharedCtx, VMSVGA3D_SHARED_CTX_ID, pSurface);
3910 AssertRCReturn(rc, rc);
3911 }
3912
3913 AssertReturn(pSurface->enmOGLResType == VMSVGA3D_OGLRESTYPE_TEXTURE, VERR_NOT_SUPPORTED);
3914
3915 PVMSVGA3DMIPMAPLEVEL pMipLevel;
3916 rc = vmsvga3dMipmapLevel(pSurface, srcImage.face, srcImage.mipmap, &pMipLevel);
3917 AssertRCReturn(rc, rc);
3918
3919 /** @todo Implement. */
3920 RT_NOREF(cRects, paRects);
3921
3922 /* GLX context is changed here, so other code has to set appropriate context again. */
3923 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
3924
3925 int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
3926
3927 Bool fSuccess = glXMakeCurrent(pState->display, p->xwindow, p->glxctx);
3928 if (fSuccess)
3929 {
3930 /* Activate the read and draw framebuffer objects. */
3931 pState->ext.glBindFramebuffer(GL_READ_FRAMEBUFFER, p->idReadFramebuffer); GLCHECK();
3932 pState->ext.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p->idDrawFramebuffer); GLCHECK();
3933
3934 /* Bind the source and destination objects to the right place. */
3935 pState->ext.glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3936 pSurface->oglId.texture, 0); GLCHECK();
3937 pState->ext.glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3938 p->idScreenTexture, 0); GLCHECK();
3939
3940 pState->ext.glBlitFramebuffer(srcRect.left,
3941 srcRect.top,
3942 srcRect.right,
3943 srcRect.bottom,
3944 destRect.left,
3945 destRect.top,
3946 destRect.right,
3947 destRect.bottom,
3948 GL_COLOR_BUFFER_BIT,
3949 GL_NEAREST); GLCHECK();
3950
3951 /* Reset the frame buffer association */
3952 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, 0); GLCHECK();
3953
3954 /* Update the overlay window. */
3955 glClear(GL_COLOR_BUFFER_BIT);
3956
3957 glBindTexture(GL_TEXTURE_2D, p->idScreenTexture); GLCHECK();
3958
3959 GLint const w = pScreen->cWidth;
3960 GLint const h = pScreen->cHeight;
3961
3962 glBegin(GL_QUADS);
3963 glTexCoord2f(0.0f, 0.0f); glVertex2i(0, h);
3964 glTexCoord2f(0.0f, 1.0f); glVertex2i(0, 0);
3965 glTexCoord2f(1.0f, 1.0f); glVertex2i(w, 0);
3966 glTexCoord2f(1.0f, 0.0f); glVertex2i(w, h);
3967 glEnd(); GLCHECK();
3968
3969 glBindTexture(GL_TEXTURE_2D, 0); GLCHECK();
3970
3971 glXMakeCurrent(pState->display, None, NULL);
3972 }
3973 else
3974 {
3975 LogRel4(("VMSVGA: vmsvga3dBackSurfaceBlitToScreen: screen %u, glXMakeCurrent for pixmap failed\n", pScreen->idScreen));
3976 }
3977
3978 XSetErrorHandler(oldHandler);
3979
3980 return VINF_SUCCESS;
3981}
3982
3983#else /* !RT_OS_LINUX */
3984
3985static DECLCALLBACK(int) vmsvga3dBackDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3986{
3987 RT_NOREF(pThis, pThisCC, pScreen);
3988 return VERR_NOT_IMPLEMENTED;
3989}
3990
3991static DECLCALLBACK(int) vmsvga3dBackDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
3992{
3993 RT_NOREF(pThisCC, pScreen);
3994 return VERR_NOT_IMPLEMENTED;
3995}
3996
3997static DECLCALLBACK(int) vmsvga3dBackSurfaceBlitToScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen,
3998 SVGASignedRect destRect, SVGA3dSurfaceImageId srcImage,
3999 SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *paRects)
4000{
4001 RT_NOREF(pThisCC, pScreen, destRect, srcImage, srcRect, cRects, paRects);
4002 return VERR_NOT_IMPLEMENTED;
4003}
4004#endif
4005
4006/**
4007 * Create a new 3d context
4008 *
4009 * @returns VBox status code.
4010 * @param pThisCC The VGA/VMSVGA state for ring-3.
4011 * @param cid Context id
4012 */
4013static DECLCALLBACK(int) vmsvga3dBackContextDefine(PVGASTATECC pThisCC, uint32_t cid)
4014{
4015 return vmsvga3dContextDefineOgl(pThisCC, cid, 0/*fFlags*/);
4016}
4017
4018/**
4019 * Destroys a 3d context.
4020 *
4021 * @returns VBox status code.
4022 * @param pThisCC The VGA/VMSVGA state for ring-3.
4023 * @param pContext The context to destroy.
4024 * @param cid Context id
4025 */
4026static int vmsvga3dContextDestroyOgl(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid)
4027{
4028 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4029 AssertReturn(pState, VERR_NO_MEMORY);
4030 AssertReturn(pContext, VERR_INVALID_PARAMETER);
4031 AssertReturn(pContext->id == cid, VERR_INVALID_PARAMETER);
4032 Log(("vmsvga3dContextDestroyOgl id %x\n", cid));
4033
4034 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4035
4036 if (pContext->id == VMSVGA3D_SHARED_CTX_ID)
4037 {
4038 /* Delete resources which use the shared context. */
4039 vmsvga3dOnSharedContextDestroy(pState);
4040 }
4041
4042 /* Destroy all leftover pixel shaders. */
4043 for (uint32_t i = 0; i < pContext->cPixelShaders; i++)
4044 {
4045 if (pContext->paPixelShader[i].id != SVGA3D_INVALID_ID)
4046 vmsvga3dBackShaderDestroy(pThisCC, pContext->paPixelShader[i].cid, pContext->paPixelShader[i].id, pContext->paPixelShader[i].type);
4047 }
4048 if (pContext->paPixelShader)
4049 RTMemFree(pContext->paPixelShader);
4050
4051 /* Destroy all leftover vertex shaders. */
4052 for (uint32_t i = 0; i < pContext->cVertexShaders; i++)
4053 {
4054 if (pContext->paVertexShader[i].id != SVGA3D_INVALID_ID)
4055 vmsvga3dBackShaderDestroy(pThisCC, pContext->paVertexShader[i].cid, pContext->paVertexShader[i].id, pContext->paVertexShader[i].type);
4056 }
4057 if (pContext->paVertexShader)
4058 RTMemFree(pContext->paVertexShader);
4059
4060 if (pContext->state.paVertexShaderConst)
4061 RTMemFree(pContext->state.paVertexShaderConst);
4062 if (pContext->state.paPixelShaderConst)
4063 RTMemFree(pContext->state.paPixelShaderConst);
4064
4065 if (pContext->pShaderContext)
4066 {
4067 int rc = ShaderContextDestroy(pContext->pShaderContext);
4068 AssertRC(rc);
4069 }
4070
4071 if (pContext->idFramebuffer != OPENGL_INVALID_ID)
4072 {
4073 /* Unbind the object from the framebuffer target. */
4074 pState->ext.glBindFramebuffer(GL_FRAMEBUFFER, 0 /* back buffer */);
4075 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4076 pState->ext.glDeleteFramebuffers(1, &pContext->idFramebuffer);
4077 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4078
4079 if (pContext->idReadFramebuffer != OPENGL_INVALID_ID)
4080 {
4081 pState->ext.glDeleteFramebuffers(1, &pContext->idReadFramebuffer);
4082 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4083 }
4084 if (pContext->idDrawFramebuffer != OPENGL_INVALID_ID)
4085 {
4086 pState->ext.glDeleteFramebuffers(1, &pContext->idDrawFramebuffer);
4087 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4088 }
4089 }
4090
4091 vmsvga3dBackOcclusionQueryDelete(pThisCC, pContext);
4092
4093#ifdef RT_OS_WINDOWS
4094 wglMakeCurrent(pContext->hdc, NULL);
4095 wglDeleteContext(pContext->hglrc);
4096 ReleaseDC(pContext->hwnd, pContext->hdc);
4097
4098 /* Destroy the window we've created. */
4099 int rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_DESTROYWINDOW, (WPARAM)pContext->hwnd, 0);
4100 AssertRC(rc);
4101#elif defined(RT_OS_DARWIN)
4102 vmsvga3dCocoaDestroyViewAndContext(pContext->cocoaView, pContext->cocoaContext);
4103#elif defined(RT_OS_LINUX)
4104 glXMakeCurrent(pState->display, None, NULL);
4105 glXDestroyContext(pState->display, pContext->glxContext);
4106 XDestroyWindow(pState->display, pContext->window);
4107#endif
4108
4109 memset(pContext, 0, sizeof(*pContext));
4110 pContext->id = SVGA3D_INVALID_ID;
4111
4112 VMSVGA3D_CLEAR_CURRENT_CONTEXT(pState);
4113 return VINF_SUCCESS;
4114}
4115
4116/**
4117 * Destroy an existing 3d context
4118 *
4119 * @returns VBox status code.
4120 * @param pThisCC The VGA/VMSVGA state for ring-3.
4121 * @param cid Context id
4122 */
4123static DECLCALLBACK(int) vmsvga3dBackContextDestroy(PVGASTATECC pThisCC, uint32_t cid)
4124{
4125 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4126 AssertReturn(pState, VERR_WRONG_ORDER);
4127
4128 /*
4129 * Resolve the context and hand it to the common worker function.
4130 */
4131 if ( cid < pState->cContexts
4132 && pState->papContexts[cid]->id == cid)
4133 return vmsvga3dContextDestroyOgl(pThisCC, pState->papContexts[cid], cid);
4134
4135 AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER);
4136 return VINF_SUCCESS;
4137}
4138
4139/**
4140 * Worker for vmsvga3dBackChangeMode that resizes a context.
4141 *
4142 * @param pState The VMSVGA3d state.
4143 * @param pContext The context.
4144 */
4145static void vmsvga3dChangeModeOneContext(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext)
4146{
4147 RT_NOREF(pState, pContext);
4148 /* Do nothing. The window is not used for presenting. */
4149}
4150
4151/* Handle resize */
4152static DECLCALLBACK(int) vmsvga3dBackChangeMode(PVGASTATECC pThisCC)
4153{
4154 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4155 AssertReturn(pState, VERR_NO_MEMORY);
4156
4157 /* Resize the shared context too. */
4158 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
4159 vmsvga3dChangeModeOneContext(pState, &pState->SharedCtx);
4160
4161 /* Resize all active contexts. */
4162 for (uint32_t i = 0; i < pState->cContexts; i++)
4163 {
4164 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
4165 if (pContext->id != SVGA3D_INVALID_ID)
4166 vmsvga3dChangeModeOneContext(pState, pContext);
4167 }
4168
4169 return VINF_SUCCESS;
4170}
4171
4172
4173static DECLCALLBACK(int) vmsvga3dBackSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16])
4174{
4175 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4176 AssertReturn(pState, VERR_NO_MEMORY);
4177 bool fModelViewChanged = false;
4178
4179 Log(("vmsvga3dSetTransform cid=%u %s\n", cid, vmsvgaTransformToString(type)));
4180
4181 ASSERT_GUEST_RETURN((unsigned)type < SVGA3D_TRANSFORM_MAX, VERR_INVALID_PARAMETER);
4182
4183 PVMSVGA3DCONTEXT pContext;
4184 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
4185 AssertRCReturn(rc, rc);
4186
4187 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4188
4189 /* Save this matrix for vm state save/restore. */
4190 pContext->state.aTransformState[type].fValid = true;
4191 memcpy(pContext->state.aTransformState[type].matrix, matrix, sizeof(pContext->state.aTransformState[type].matrix));
4192 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_TRANSFORM;
4193
4194 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)));
4195 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)));
4196 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)));
4197 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)));
4198
4199 switch (type)
4200 {
4201 case SVGA3D_TRANSFORM_VIEW:
4202 /* View * World = Model View */
4203 glMatrixMode(GL_MODELVIEW);
4204 glLoadMatrixf(matrix);
4205 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_WORLD].fValid)
4206 glMultMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_WORLD].matrix);
4207 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4208 fModelViewChanged = true;
4209 break;
4210
4211 case SVGA3D_TRANSFORM_PROJECTION:
4212 {
4213 rc = ShaderTransformProjection(pContext->state.RectViewPort.w, pContext->state.RectViewPort.h, matrix, false /* fPretransformed */);
4214 AssertRCReturn(rc, rc);
4215 break;
4216 }
4217
4218 case SVGA3D_TRANSFORM_TEXTURE0:
4219 glMatrixMode(GL_TEXTURE);
4220 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4221 glLoadMatrixf(matrix);
4222 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4223 break;
4224
4225 case SVGA3D_TRANSFORM_TEXTURE1:
4226 case SVGA3D_TRANSFORM_TEXTURE2:
4227 case SVGA3D_TRANSFORM_TEXTURE3:
4228 case SVGA3D_TRANSFORM_TEXTURE4:
4229 case SVGA3D_TRANSFORM_TEXTURE5:
4230 case SVGA3D_TRANSFORM_TEXTURE6:
4231 case SVGA3D_TRANSFORM_TEXTURE7:
4232 Log(("vmsvga3dSetTransform: unsupported SVGA3D_TRANSFORM_TEXTUREx transform!!\n"));
4233 return VERR_INVALID_PARAMETER;
4234
4235 case SVGA3D_TRANSFORM_WORLD:
4236 /* View * World = Model View */
4237 glMatrixMode(GL_MODELVIEW);
4238 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].fValid)
4239 glLoadMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix);
4240 else
4241 glLoadIdentity();
4242 glMultMatrixf(matrix);
4243 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4244 fModelViewChanged = true;
4245 break;
4246
4247 case SVGA3D_TRANSFORM_WORLD1:
4248 case SVGA3D_TRANSFORM_WORLD2:
4249 case SVGA3D_TRANSFORM_WORLD3:
4250 Log(("vmsvga3dSetTransform: unsupported SVGA3D_TRANSFORM_WORLDx transform!!\n"));
4251 return VERR_INVALID_PARAMETER;
4252
4253 default:
4254 Log(("vmsvga3dSetTransform: unknown type!!\n"));
4255 return VERR_INVALID_PARAMETER;
4256 }
4257
4258 /* Apparently we need to reset the light and clip data after modifying the modelview matrix. */
4259 if (fModelViewChanged)
4260 {
4261 /* Reprogram the clip planes. */
4262 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aClipPlane); j++)
4263 {
4264 if (pContext->state.aClipPlane[j].fValid == true)
4265 vmsvga3dBackSetClipPlane(pThisCC, cid, j, pContext->state.aClipPlane[j].plane);
4266 }
4267
4268 /* Reprogram the light data. */
4269 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aLightData); j++)
4270 {
4271 if (pContext->state.aLightData[j].fValidData == true)
4272 vmsvga3dBackSetLightData(pThisCC, cid, j, &pContext->state.aLightData[j].data);
4273 }
4274 }
4275
4276 return VINF_SUCCESS;
4277}
4278
4279static DECLCALLBACK(int) vmsvga3dBackSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange)
4280{
4281 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4282 AssertReturn(pState, VERR_NO_MEMORY);
4283
4284 Log(("vmsvga3dSetZRange cid=%u min=%d max=%d\n", cid, (uint32_t)(zRange.min * 100.0), (uint32_t)(zRange.max * 100.0)));
4285
4286 PVMSVGA3DCONTEXT pContext;
4287 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
4288 AssertRCReturn(rc, rc);
4289
4290 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4291
4292 pContext->state.zRange = zRange;
4293 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_ZRANGE;
4294
4295 if (zRange.min < -1.0)
4296 zRange.min = -1.0;
4297 if (zRange.max > 1.0)
4298 zRange.max = 1.0;
4299
4300 glDepthRange((GLdouble)zRange.min, (GLdouble)zRange.max);
4301 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4302 return VINF_SUCCESS;
4303}
4304
4305/**
4306 * Convert SVGA blend op value to its OpenGL equivalent
4307 */
4308static GLenum vmsvga3dBlendOp2GL(uint32_t blendOp)
4309{
4310 switch (blendOp)
4311 {
4312 case SVGA3D_BLENDOP_ZERO:
4313 return GL_ZERO;
4314 case SVGA3D_BLENDOP_ONE:
4315 return GL_ONE;
4316 case SVGA3D_BLENDOP_SRCCOLOR:
4317 return GL_SRC_COLOR;
4318 case SVGA3D_BLENDOP_INVSRCCOLOR:
4319 return GL_ONE_MINUS_SRC_COLOR;
4320 case SVGA3D_BLENDOP_SRCALPHA:
4321 return GL_SRC_ALPHA;
4322 case SVGA3D_BLENDOP_INVSRCALPHA:
4323 return GL_ONE_MINUS_SRC_ALPHA;
4324 case SVGA3D_BLENDOP_DESTALPHA:
4325 return GL_DST_ALPHA;
4326 case SVGA3D_BLENDOP_INVDESTALPHA:
4327 return GL_ONE_MINUS_DST_ALPHA;
4328 case SVGA3D_BLENDOP_DESTCOLOR:
4329 return GL_DST_COLOR;
4330 case SVGA3D_BLENDOP_INVDESTCOLOR:
4331 return GL_ONE_MINUS_DST_COLOR;
4332 case SVGA3D_BLENDOP_SRCALPHASAT:
4333 return GL_SRC_ALPHA_SATURATE;
4334 case SVGA3D_BLENDOP_BLENDFACTOR:
4335 return GL_CONSTANT_COLOR;
4336 case SVGA3D_BLENDOP_INVBLENDFACTOR:
4337 return GL_ONE_MINUS_CONSTANT_COLOR;
4338 default:
4339 AssertFailed();
4340 return GL_ONE;
4341 }
4342}
4343
4344static GLenum vmsvga3dBlendEquation2GL(uint32_t blendEq)
4345{
4346 switch (blendEq)
4347 {
4348 case SVGA3D_BLENDEQ_ADD:
4349 return GL_FUNC_ADD;
4350 case SVGA3D_BLENDEQ_SUBTRACT:
4351 return GL_FUNC_SUBTRACT;
4352 case SVGA3D_BLENDEQ_REVSUBTRACT:
4353 return GL_FUNC_REVERSE_SUBTRACT;
4354 case SVGA3D_BLENDEQ_MINIMUM:
4355 return GL_MIN;
4356 case SVGA3D_BLENDEQ_MAXIMUM:
4357 return GL_MAX;
4358 default:
4359 /* SVGA3D_BLENDEQ_INVALID means that the render state has not been set, therefore use default. */
4360 AssertMsg(blendEq == SVGA3D_BLENDEQ_INVALID, ("blendEq=%d (%#x)\n", blendEq, blendEq));
4361 return GL_FUNC_ADD;
4362 }
4363}
4364
4365static GLenum vmsvgaCmpFunc2GL(uint32_t cmpFunc)
4366{
4367 switch (cmpFunc)
4368 {
4369 case SVGA3D_CMP_NEVER:
4370 return GL_NEVER;
4371 case SVGA3D_CMP_LESS:
4372 return GL_LESS;
4373 case SVGA3D_CMP_EQUAL:
4374 return GL_EQUAL;
4375 case SVGA3D_CMP_LESSEQUAL:
4376 return GL_LEQUAL;
4377 case SVGA3D_CMP_GREATER:
4378 return GL_GREATER;
4379 case SVGA3D_CMP_NOTEQUAL:
4380 return GL_NOTEQUAL;
4381 case SVGA3D_CMP_GREATEREQUAL:
4382 return GL_GEQUAL;
4383 case SVGA3D_CMP_ALWAYS:
4384 return GL_ALWAYS;
4385 default:
4386 Assert(cmpFunc == SVGA3D_CMP_INVALID);
4387 return GL_LESS;
4388 }
4389}
4390
4391static GLenum vmsvgaStencipOp2GL(uint32_t stencilOp)
4392{
4393 switch (stencilOp)
4394 {
4395 case SVGA3D_STENCILOP_KEEP:
4396 return GL_KEEP;
4397 case SVGA3D_STENCILOP_ZERO:
4398 return GL_ZERO;
4399 case SVGA3D_STENCILOP_REPLACE:
4400 return GL_REPLACE;
4401 case SVGA3D_STENCILOP_INCRSAT:
4402 return GL_INCR_WRAP;
4403 case SVGA3D_STENCILOP_DECRSAT:
4404 return GL_DECR_WRAP;
4405 case SVGA3D_STENCILOP_INVERT:
4406 return GL_INVERT;
4407 case SVGA3D_STENCILOP_INCR:
4408 return GL_INCR;
4409 case SVGA3D_STENCILOP_DECR:
4410 return GL_DECR;
4411 default:
4412 Assert(stencilOp == SVGA3D_STENCILOP_INVALID);
4413 return GL_KEEP;
4414 }
4415}
4416
4417static DECLCALLBACK(int) vmsvga3dBackSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState)
4418{
4419 uint32_t val = UINT32_MAX; /* Shut up MSC. */
4420 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
4421 AssertReturn(pState, VERR_NO_MEMORY);
4422
4423 Log(("vmsvga3dSetRenderState cid=%u cRenderStates=%d\n", cid, cRenderStates));
4424
4425 PVMSVGA3DCONTEXT pContext;
4426 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
4427 AssertRCReturn(rc, rc);
4428
4429 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
4430
4431 for (unsigned i = 0; i < cRenderStates; i++)
4432 {
4433 GLenum enableCap = ~(GLenum)0;
4434 Log(("vmsvga3dSetRenderState: cid=%u state=%s (%d) val=%x\n", cid, vmsvga3dGetRenderStateName(pRenderState[i].state), pRenderState[i].state, pRenderState[i].uintValue));
4435 /* Save the render state for vm state saving. */
4436 ASSERT_GUEST_RETURN((unsigned)pRenderState[i].state < SVGA3D_RS_MAX, VERR_INVALID_PARAMETER);
4437 pContext->state.aRenderState[pRenderState[i].state] = pRenderState[i];
4438
4439 switch (pRenderState[i].state)
4440 {
4441 case SVGA3D_RS_ZENABLE: /* SVGA3dBool */
4442 enableCap = GL_DEPTH_TEST;
4443 val = pRenderState[i].uintValue;
4444 break;
4445
4446 case SVGA3D_RS_ZWRITEENABLE: /* SVGA3dBool */
4447 glDepthMask(!!pRenderState[i].uintValue);
4448 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4449 break;
4450
4451 case SVGA3D_RS_ALPHATESTENABLE: /* SVGA3dBool */
4452 enableCap = GL_ALPHA_TEST;
4453 val = pRenderState[i].uintValue;
4454 break;
4455
4456 case SVGA3D_RS_DITHERENABLE: /* SVGA3dBool */
4457 enableCap = GL_DITHER;
4458 val = pRenderState[i].uintValue;
4459 break;
4460
4461 case SVGA3D_RS_FOGENABLE: /* SVGA3dBool */
4462 enableCap = GL_FOG;
4463 val = pRenderState[i].uintValue;
4464 break;
4465
4466 case SVGA3D_RS_SPECULARENABLE: /* SVGA3dBool */
4467 Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n"));
4468 break;
4469
4470 case SVGA3D_RS_LIGHTINGENABLE: /* SVGA3dBool */
4471 enableCap = GL_LIGHTING;
4472 val = pRenderState[i].uintValue;
4473 break;
4474
4475 case SVGA3D_RS_NORMALIZENORMALS: /* SVGA3dBool */
4476 /* not applicable */
4477 Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n"));
4478 break;
4479
4480 case SVGA3D_RS_POINTSPRITEENABLE: /* SVGA3dBool */
4481 enableCap = GL_POINT_SPRITE_ARB;
4482 val = pRenderState[i].uintValue;
4483 break;
4484
4485 case SVGA3D_RS_POINTSIZE: /* float */
4486 /** @todo we need to apply scaling for point sizes below the min or above the max; see Wine) */
4487 if (pRenderState[i].floatValue < pState->caps.flPointSize[0])
4488 pRenderState[i].floatValue = pState->caps.flPointSize[0];
4489 if (pRenderState[i].floatValue > pState->caps.flPointSize[1])
4490 pRenderState[i].floatValue = pState->caps.flPointSize[1];
4491
4492 glPointSize(pRenderState[i].floatValue);
4493 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4494 Log(("SVGA3D_RS_POINTSIZE: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
4495 break;
4496
4497 case SVGA3D_RS_POINTSIZEMIN: /* float */
4498 pState->ext.glPointParameterf(GL_POINT_SIZE_MIN, pRenderState[i].floatValue);
4499 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4500 Log(("SVGA3D_RS_POINTSIZEMIN: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
4501 break;
4502
4503 case SVGA3D_RS_POINTSIZEMAX: /* float */
4504 pState->ext.glPointParameterf(GL_POINT_SIZE_MAX, pRenderState[i].floatValue);
4505 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4506 Log(("SVGA3D_RS_POINTSIZEMAX: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
4507 break;
4508
4509 case SVGA3D_RS_POINTSCALEENABLE: /* SVGA3dBool */
4510 case SVGA3D_RS_POINTSCALE_A: /* float */
4511 case SVGA3D_RS_POINTSCALE_B: /* float */
4512 case SVGA3D_RS_POINTSCALE_C: /* float */
4513 Log(("vmsvga3dSetRenderState: WARNING: not applicable.\n"));
4514 break;
4515
4516 case SVGA3D_RS_AMBIENT: /* SVGA3dColor */
4517 {
4518 GLfloat color[4]; /* red, green, blue, alpha */
4519
4520 vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &color[0], &color[1], &color[2], &color[3]);
4521
4522 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color);
4523 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4524 break;
4525 }
4526
4527 case SVGA3D_RS_CLIPPLANEENABLE: /* SVGA3dClipPlanes */
4528 {
4529 for (uint32_t j = 0; j < SVGA3D_NUM_CLIPPLANES; j++)
4530 {
4531 if (pRenderState[i].uintValue & RT_BIT(j))
4532 glEnable(GL_CLIP_PLANE0 + j);
4533 else
4534 glDisable(GL_CLIP_PLANE0 + j);
4535 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4536 }
4537 break;
4538 }
4539
4540 case SVGA3D_RS_FOGCOLOR: /* SVGA3dColor */
4541 {
4542 GLfloat color[4]; /* red, green, blue, alpha */
4543
4544 vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &color[0], &color[1], &color[2], &color[3]);
4545
4546 glFogfv(GL_FOG_COLOR, color);
4547 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4548 break;
4549 }
4550
4551 case SVGA3D_RS_FOGSTART: /* float */
4552 glFogf(GL_FOG_START, pRenderState[i].floatValue);
4553 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4554 break;
4555
4556 case SVGA3D_RS_FOGEND: /* float */
4557 glFogf(GL_FOG_END, pRenderState[i].floatValue);
4558 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4559 break;
4560
4561 case SVGA3D_RS_FOGDENSITY: /* float */
4562 glFogf(GL_FOG_DENSITY, pRenderState[i].floatValue);
4563 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4564 break;
4565
4566 case SVGA3D_RS_RANGEFOGENABLE: /* SVGA3dBool */
4567 glFogi(GL_FOG_COORD_SRC, (pRenderState[i].uintValue) ? GL_FOG_COORD : GL_FRAGMENT_DEPTH);
4568 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4569 break;
4570
4571 case SVGA3D_RS_FOGMODE: /* SVGA3dFogMode */
4572 {
4573 SVGA3dFogMode mode;
4574 mode.uintValue = pRenderState[i].uintValue;
4575
4576 enableCap = GL_FOG_MODE;
4577 switch (mode.function)
4578 {
4579 case SVGA3D_FOGFUNC_EXP:
4580 val = GL_EXP;
4581 break;
4582 case SVGA3D_FOGFUNC_EXP2:
4583 val = GL_EXP2;
4584 break;
4585 case SVGA3D_FOGFUNC_LINEAR:
4586 val = GL_LINEAR;
4587 break;
4588 default:
4589 AssertMsgFailedReturn(("Unexpected fog function %d\n", mode.function), VERR_INTERNAL_ERROR);
4590 break;
4591 }
4592
4593 /** @todo how to switch between vertex and pixel fog modes??? */
4594 Assert(mode.type == SVGA3D_FOGTYPE_PIXEL);
4595#if 0
4596 /* The fog type determines the render state. */
4597 switch (mode.type)
4598 {
4599 case SVGA3D_FOGTYPE_VERTEX:
4600 renderState = D3DRS_FOGVERTEXMODE;
4601 break;
4602 case SVGA3D_FOGTYPE_PIXEL:
4603 renderState = D3DRS_FOGTABLEMODE;
4604 break;
4605 default:
4606 AssertMsgFailedReturn(("Unexpected fog type %d\n", mode.type), VERR_INTERNAL_ERROR);
4607 break;
4608 }
4609#endif
4610
4611 /* Set the fog base to depth or range. */
4612 switch (mode.base)
4613 {
4614 case SVGA3D_FOGBASE_DEPTHBASED:
4615 glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
4616 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4617 break;
4618 case SVGA3D_FOGBASE_RANGEBASED:
4619 glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD);
4620 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4621 break;
4622 default:
4623 /* ignore */
4624 AssertMsgFailed(("Unexpected fog base %d\n", mode.base));
4625 break;
4626 }
4627 break;
4628 }
4629
4630 case SVGA3D_RS_FILLMODE: /* SVGA3dFillMode */
4631 {
4632 SVGA3dFillMode mode;
4633
4634 mode.uintValue = pRenderState[i].uintValue;
4635
4636 switch (mode.mode)
4637 {
4638 case SVGA3D_FILLMODE_POINT:
4639 val = GL_POINT;
4640 break;
4641 case SVGA3D_FILLMODE_LINE:
4642 val = GL_LINE;
4643 break;
4644 case SVGA3D_FILLMODE_FILL:
4645 val = GL_FILL;
4646 break;
4647 default:
4648 AssertMsgFailedReturn(("Unexpected fill mode %d\n", mode.mode), VERR_INTERNAL_ERROR);
4649 break;
4650 }
4651 /* Only front and back faces. Also recent Mesa guest drivers initialize the 'face' to zero. */
4652 ASSERT_GUEST(mode.face == SVGA3D_FACE_FRONT_BACK || mode.face == SVGA3D_FACE_INVALID);
4653 glPolygonMode(GL_FRONT_AND_BACK, val);
4654 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4655 break;
4656 }
4657
4658 case SVGA3D_RS_SHADEMODE: /* SVGA3dShadeMode */
4659 switch (pRenderState[i].uintValue)
4660 {
4661 case SVGA3D_SHADEMODE_FLAT:
4662 val = GL_FLAT;
4663 break;
4664
4665 case SVGA3D_SHADEMODE_SMOOTH:
4666 val = GL_SMOOTH;
4667 break;
4668
4669 default:
4670 AssertMsgFailedReturn(("Unexpected shade mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR);
4671 break;
4672 }
4673
4674 glShadeModel(val);
4675 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4676 break;
4677
4678 case SVGA3D_RS_LINEPATTERN: /* SVGA3dLinePattern */
4679 /* No longer supported by d3d; mesagl comments suggest not all backends support it */
4680 /** @todo */
4681 Log(("WARNING: SVGA3D_RS_LINEPATTERN %x not supported!!\n", pRenderState[i].uintValue));
4682 /*
4683 renderState = D3DRS_LINEPATTERN;
4684 val = pRenderState[i].uintValue;
4685 */
4686 break;
4687
4688 case SVGA3D_RS_ANTIALIASEDLINEENABLE: /* SVGA3dBool */
4689 enableCap = GL_LINE_SMOOTH;
4690 val = pRenderState[i].uintValue;
4691 break;
4692
4693 case SVGA3D_RS_LINEWIDTH: /* float */
4694 glLineWidth(pRenderState[i].floatValue);
4695 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4696 break;
4697
4698 case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */
4699 {
4700 /* Refresh the blending state based on the new enable setting.
4701 * This will take existing states and set them using either glBlend* or glBlend*Separate.
4702 */
4703 static SVGA3dRenderStateName const saRefreshState[] =
4704 {
4705 SVGA3D_RS_SRCBLEND,
4706 SVGA3D_RS_BLENDEQUATION
4707 };
4708 SVGA3dRenderState renderstate[RT_ELEMENTS(saRefreshState)];
4709 for (uint32_t j = 0; j < RT_ELEMENTS(saRefreshState); ++j)
4710 {
4711 renderstate[j].state = saRefreshState[j];
4712 renderstate[j].uintValue = pContext->state.aRenderState[saRefreshState[j]].uintValue;
4713 }
4714
4715 rc = vmsvga3dBackSetRenderState(pThisCC, cid, 2, renderstate);
4716 AssertRCReturn(rc, rc);
4717
4718 if (pContext->state.aRenderState[SVGA3D_RS_BLENDENABLE].uintValue != 0)
4719 continue; /* Ignore if blend is enabled */
4720 /* Apply SVGA3D_RS_SEPARATEALPHABLENDENABLE as SVGA3D_RS_BLENDENABLE */
4721 } RT_FALL_THRU();
4722
4723 case SVGA3D_RS_BLENDENABLE: /* SVGA3dBool */
4724 enableCap = GL_BLEND;
4725 val = pRenderState[i].uintValue;
4726 break;
4727
4728 case SVGA3D_RS_SRCBLENDALPHA: /* SVGA3dBlendOp */
4729 case SVGA3D_RS_DSTBLENDALPHA: /* SVGA3dBlendOp */
4730 case SVGA3D_RS_SRCBLEND: /* SVGA3dBlendOp */
4731 case SVGA3D_RS_DSTBLEND: /* SVGA3dBlendOp */
4732 {
4733 GLint srcRGB, srcAlpha, dstRGB, dstAlpha;
4734 GLint blendop = vmsvga3dBlendOp2GL(pRenderState[i].uintValue);
4735
4736 glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB);
4737 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4738 glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB);
4739 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4740 glGetIntegerv(GL_BLEND_DST_ALPHA, &dstAlpha);
4741 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4742 glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcAlpha);
4743 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4744
4745 switch (pRenderState[i].state)
4746 {
4747 case SVGA3D_RS_SRCBLEND:
4748 srcRGB = blendop;
4749 break;
4750 case SVGA3D_RS_DSTBLEND:
4751 dstRGB = blendop;
4752 break;
4753 case SVGA3D_RS_SRCBLENDALPHA:
4754 srcAlpha = blendop;
4755 break;
4756 case SVGA3D_RS_DSTBLENDALPHA:
4757 dstAlpha = blendop;
4758 break;
4759 default:
4760 /* not possible; shut up gcc */
4761 AssertFailed();
4762 break;
4763 }
4764
4765 if (pContext->state.aRenderState[SVGA3D_RS_SEPARATEALPHABLENDENABLE].uintValue != 0)
4766 pState->ext.glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
4767 else
4768 glBlendFunc(srcRGB, dstRGB);
4769 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4770 break;
4771 }
4772
4773 case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation */
4774 case SVGA3D_RS_BLENDEQUATION: /* SVGA3dBlendEquation */
4775 if (pContext->state.aRenderState[SVGA3D_RS_SEPARATEALPHABLENDENABLE].uintValue != 0)
4776 {
4777 GLenum const modeRGB = vmsvga3dBlendEquation2GL(pContext->state.aRenderState[SVGA3D_RS_BLENDEQUATION].uintValue);
4778 GLenum const modeAlpha = vmsvga3dBlendEquation2GL(pContext->state.aRenderState[SVGA3D_RS_BLENDEQUATIONALPHA].uintValue);
4779 pState->ext.glBlendEquationSeparate(modeRGB, modeAlpha);
4780 }
4781 else
4782 {
4783#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x102
4784 glBlendEquation(vmsvga3dBlendEquation2GL(pRenderState[i].uintValue));
4785#else
4786 pState->ext.glBlendEquation(vmsvga3dBlendEquation2GL(pRenderState[i].uintValue));
4787#endif
4788 }
4789 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4790 break;
4791
4792 case SVGA3D_RS_BLENDCOLOR: /* SVGA3dColor */
4793 {
4794 GLfloat red, green, blue, alpha;
4795
4796 vmsvgaColor2GLFloatArray(pRenderState[i].uintValue, &red, &green, &blue, &alpha);
4797
4798#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x102
4799 glBlendColor(red, green, blue, alpha);
4800#else
4801 pState->ext.glBlendColor(red, green, blue, alpha);
4802#endif
4803 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4804 break;
4805 }
4806
4807 case SVGA3D_RS_CULLMODE: /* SVGA3dFace */
4808 {
4809 GLenum mode = GL_BACK; /* default for OpenGL */
4810
4811 switch (pRenderState[i].uintValue)
4812 {
4813 case SVGA3D_FACE_NONE:
4814 break;
4815 case SVGA3D_FACE_FRONT:
4816 mode = GL_FRONT;
4817 break;
4818 case SVGA3D_FACE_BACK:
4819 mode = GL_BACK;
4820 break;
4821 case SVGA3D_FACE_FRONT_BACK:
4822 mode = GL_FRONT_AND_BACK;
4823 break;
4824 default:
4825 AssertMsgFailedReturn(("Unexpected cull mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR);
4826 break;
4827 }
4828 enableCap = GL_CULL_FACE;
4829 if (pRenderState[i].uintValue != SVGA3D_FACE_NONE)
4830 {
4831 glCullFace(mode);
4832 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4833 val = 1;
4834 }
4835 else
4836 val = 0;
4837 break;
4838 }
4839
4840 case SVGA3D_RS_ZFUNC: /* SVGA3dCmpFunc */
4841 glDepthFunc(vmsvgaCmpFunc2GL(pRenderState[i].uintValue));
4842 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4843 break;
4844
4845 case SVGA3D_RS_ALPHAFUNC: /* SVGA3dCmpFunc */
4846 {
4847 GLclampf ref;
4848
4849 glGetFloatv(GL_ALPHA_TEST_REF, &ref);
4850 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4851 glAlphaFunc(vmsvgaCmpFunc2GL(pRenderState[i].uintValue), ref);
4852 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4853 break;
4854 }
4855
4856 case SVGA3D_RS_ALPHAREF: /* float (0.0 .. 1.0) */
4857 {
4858 GLint func;
4859
4860 glGetIntegerv(GL_ALPHA_TEST_FUNC, &func);
4861 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4862 glAlphaFunc(func, pRenderState[i].floatValue);
4863 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4864 break;
4865 }
4866
4867 case SVGA3D_RS_STENCILENABLE2SIDED: /* SVGA3dBool */
4868 {
4869 /* Refresh the stencil state based on the new enable setting.
4870 * This will take existing states and set them using either glStencil or glStencil*Separate.
4871 */
4872 static SVGA3dRenderStateName const saRefreshState[] =
4873 {
4874 SVGA3D_RS_STENCILFUNC,
4875 SVGA3D_RS_STENCILFAIL,
4876 SVGA3D_RS_CCWSTENCILFUNC,
4877 SVGA3D_RS_CCWSTENCILFAIL
4878 };
4879 SVGA3dRenderState renderstate[RT_ELEMENTS(saRefreshState)];
4880 for (uint32_t j = 0; j < RT_ELEMENTS(saRefreshState); ++j)
4881 {
4882 renderstate[j].state = saRefreshState[j];
4883 renderstate[j].uintValue = pContext->state.aRenderState[saRefreshState[j]].uintValue;
4884 }
4885
4886 rc = vmsvga3dBackSetRenderState(pThisCC, cid, RT_ELEMENTS(renderstate), renderstate);
4887 AssertRCReturn(rc, rc);
4888
4889 if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE].uintValue != 0)
4890 continue; /* Ignore if stencil is enabled */
4891 /* Apply SVGA3D_RS_STENCILENABLE2SIDED as SVGA3D_RS_STENCILENABLE. */
4892 } RT_FALL_THRU();
4893
4894 case SVGA3D_RS_STENCILENABLE: /* SVGA3dBool */
4895 enableCap = GL_STENCIL_TEST;
4896 val = pRenderState[i].uintValue;
4897 break;
4898
4899 case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc */
4900 case SVGA3D_RS_STENCILREF: /* uint32_t */
4901 case SVGA3D_RS_STENCILMASK: /* uint32_t */
4902 {
4903 GLint func, ref;
4904 GLuint mask;
4905
4906 /* Query current values to have all parameters for glStencilFunc[Separate]. */
4907 glGetIntegerv(GL_STENCIL_FUNC, &func);
4908 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4909 glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&mask);
4910 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4911 glGetIntegerv(GL_STENCIL_REF, &ref);
4912 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4913
4914 /* Update the changed value. */
4915 switch (pRenderState[i].state)
4916 {
4917 case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc */
4918 func = vmsvgaCmpFunc2GL(pRenderState[i].uintValue);
4919 break;
4920
4921 case SVGA3D_RS_STENCILREF: /* uint32_t */
4922 ref = pRenderState[i].uintValue;
4923 break;
4924
4925 case SVGA3D_RS_STENCILMASK: /* uint32_t */
4926 mask = pRenderState[i].uintValue;
4927 break;
4928
4929 default:
4930 /* not possible; shut up gcc */
4931 AssertFailed();
4932 break;
4933 }
4934
4935 if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE2SIDED].uintValue != 0)
4936 {
4937 pState->ext.glStencilFuncSeparate(GL_FRONT, func, ref, mask);
4938 }
4939 else
4940 {
4941 glStencilFunc(func, ref, mask);
4942 }
4943 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4944 break;
4945 }
4946
4947 case SVGA3D_RS_STENCILWRITEMASK: /* uint32_t */
4948 glStencilMask(pRenderState[i].uintValue);
4949 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4950 break;
4951
4952 case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp */
4953 case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp */
4954 case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp */
4955 {
4956 GLint sfail, dpfail, dppass;
4957 GLenum const stencilop = vmsvgaStencipOp2GL(pRenderState[i].uintValue);
4958
4959 glGetIntegerv(GL_STENCIL_FAIL, &sfail);
4960 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4961 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &dpfail);
4962 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4963 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &dppass);
4964 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4965
4966 switch (pRenderState[i].state)
4967 {
4968 case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp */
4969 sfail = stencilop;
4970 break;
4971 case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp */
4972 dpfail = stencilop;
4973 break;
4974 case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp */
4975 dppass = stencilop;
4976 break;
4977 default:
4978 /* not possible; shut up gcc */
4979 AssertFailed();
4980 break;
4981 }
4982 if (pContext->state.aRenderState[SVGA3D_RS_STENCILENABLE2SIDED].uintValue != 0)
4983 {
4984 pState->ext.glStencilOpSeparate(GL_FRONT, sfail, dpfail, dppass);
4985 }
4986 else
4987 {
4988 glStencilOp(sfail, dpfail, dppass);
4989 }
4990 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
4991 break;
4992 }
4993
4994 case SVGA3D_RS_CCWSTENCILFUNC: /* SVGA3dCmpFunc */
4995 {
4996 GLint ref;
4997 GLuint mask;
4998 GLint const func = vmsvgaCmpFunc2GL(pRenderState[i].uintValue);
4999
5000 /* GL_STENCIL_VALUE_MASK and GL_STENCIL_REF are the same for both GL_FRONT and GL_BACK. */
5001 glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)&mask);
5002 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5003 glGetIntegerv(GL_STENCIL_REF, &ref);
5004 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5005
5006 pState->ext.glStencilFuncSeparate(GL_BACK, func, ref, mask);
5007 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5008 break;
5009 }
5010
5011 case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp */
5012 case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp */
5013 case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp */
5014 {
5015 GLint sfail, dpfail, dppass;
5016 GLenum const stencilop = vmsvgaStencipOp2GL(pRenderState[i].uintValue);
5017
5018 glGetIntegerv(GL_STENCIL_BACK_FAIL, &sfail);
5019 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5020 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &dpfail);
5021 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5022 glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &dppass);
5023 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5024
5025 switch (pRenderState[i].state)
5026 {
5027 case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp */
5028 sfail = stencilop;
5029 break;
5030 case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp */
5031 dpfail = stencilop;
5032 break;
5033 case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp */
5034 dppass = stencilop;
5035 break;
5036 default:
5037 /* not possible; shut up gcc */
5038 AssertFailed();
5039 break;
5040 }
5041 pState->ext.glStencilOpSeparate(GL_BACK, sfail, dpfail, dppass);
5042 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5043 break;
5044 }
5045
5046 case SVGA3D_RS_ZBIAS: /* float */
5047 /** @todo unknown meaning; depth bias is not identical
5048 renderState = D3DRS_DEPTHBIAS;
5049 val = pRenderState[i].uintValue;
5050 */
5051 Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_RS_ZBIAS\n"));
5052 break;
5053
5054 case SVGA3D_RS_DEPTHBIAS: /* float */
5055 {
5056 GLfloat factor;
5057
5058 /** @todo not sure if the d3d & ogl definitions are identical. */
5059
5060 /* Do not change the factor part. */
5061 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &factor);
5062 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5063
5064 glPolygonOffset(factor, pRenderState[i].floatValue);
5065 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5066 break;
5067 }
5068
5069 case SVGA3D_RS_SLOPESCALEDEPTHBIAS: /* float */
5070 {
5071 GLfloat units;
5072
5073 /** @todo not sure if the d3d & ogl definitions are identical. */
5074
5075 /* Do not change the factor part. */
5076 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &units);
5077 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5078
5079 glPolygonOffset(pRenderState[i].floatValue, units);
5080 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5081 break;
5082 }
5083
5084 case SVGA3D_RS_COLORWRITEENABLE: /* SVGA3dColorMask */
5085 {
5086 GLboolean red, green, blue, alpha;
5087 SVGA3dColorMask mask;
5088
5089 mask.uintValue = pRenderState[i].uintValue;
5090
5091 red = mask.red;
5092 green = mask.green;
5093 blue = mask.blue;
5094 alpha = mask.alpha;
5095
5096 glColorMask(red, green, blue, alpha);
5097 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5098 break;
5099 }
5100
5101 case SVGA3D_RS_COLORWRITEENABLE1: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */
5102 case SVGA3D_RS_COLORWRITEENABLE2: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */
5103 case SVGA3D_RS_COLORWRITEENABLE3: /* SVGA3dColorMask to D3DCOLORWRITEENABLE_* */
5104 Log(("vmsvga3dSetRenderState: WARNING SVGA3D_RS_COLORWRITEENABLEx not supported!!\n"));
5105 break;
5106
5107 case SVGA3D_RS_SCISSORTESTENABLE: /* SVGA3dBool */
5108 enableCap = GL_SCISSOR_TEST;
5109 val = pRenderState[i].uintValue;
5110 break;
5111
5112#if 0
5113 case SVGA3D_RS_DIFFUSEMATERIALSOURCE: /* SVGA3dVertexMaterial */
5114 AssertCompile(D3DMCS_COLOR2 == SVGA3D_VERTEXMATERIAL_SPECULAR);
5115 renderState = D3DRS_DIFFUSEMATERIALSOURCE;
5116 val = pRenderState[i].uintValue;
5117 break;
5118
5119 case SVGA3D_RS_SPECULARMATERIALSOURCE: /* SVGA3dVertexMaterial */
5120 renderState = D3DRS_SPECULARMATERIALSOURCE;
5121 val = pRenderState[i].uintValue;
5122 break;
5123
5124 case SVGA3D_RS_AMBIENTMATERIALSOURCE: /* SVGA3dVertexMaterial */
5125 renderState = D3DRS_AMBIENTMATERIALSOURCE;
5126 val = pRenderState[i].uintValue;
5127 break;
5128
5129 case SVGA3D_RS_EMISSIVEMATERIALSOURCE: /* SVGA3dVertexMaterial */
5130 renderState = D3DRS_EMISSIVEMATERIALSOURCE;
5131 val = pRenderState[i].uintValue;
5132 break;
5133#endif
5134
5135 case SVGA3D_RS_WRAP3: /* SVGA3dWrapFlags */
5136 case SVGA3D_RS_WRAP4: /* SVGA3dWrapFlags */
5137 case SVGA3D_RS_WRAP5: /* SVGA3dWrapFlags */
5138 case SVGA3D_RS_WRAP6: /* SVGA3dWrapFlags */
5139 case SVGA3D_RS_WRAP7: /* SVGA3dWrapFlags */
5140 case SVGA3D_RS_WRAP8: /* SVGA3dWrapFlags */
5141 case SVGA3D_RS_WRAP9: /* SVGA3dWrapFlags */
5142 case SVGA3D_RS_WRAP10: /* SVGA3dWrapFlags */
5143 case SVGA3D_RS_WRAP11: /* SVGA3dWrapFlags */
5144 case SVGA3D_RS_WRAP12: /* SVGA3dWrapFlags */
5145 case SVGA3D_RS_WRAP13: /* SVGA3dWrapFlags */
5146 case SVGA3D_RS_WRAP14: /* SVGA3dWrapFlags */
5147 case SVGA3D_RS_WRAP15: /* SVGA3dWrapFlags */
5148 Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_WRAPx (x >= 3)\n"));
5149 break;
5150
5151 case SVGA3D_RS_LASTPIXEL: /* SVGA3dBool */
5152 case SVGA3D_RS_TWEENFACTOR: /* float */
5153 case SVGA3D_RS_INDEXEDVERTEXBLENDENABLE: /* SVGA3dBool */
5154 case SVGA3D_RS_VERTEXBLEND: /* SVGA3dVertexBlendFlags */
5155 Log(("vmsvga3dSetRenderState: WARNING not applicable!!\n"));
5156 break;
5157
5158 case SVGA3D_RS_MULTISAMPLEANTIALIAS: /* SVGA3dBool */
5159 enableCap = GL_MULTISAMPLE;
5160 val = pRenderState[i].uintValue;
5161 break;
5162
5163 case SVGA3D_RS_MULTISAMPLEMASK: /* uint32_t */
5164 Log(("vmsvga3dSetRenderState: WARNING not applicable??!!\n"));
5165 break;
5166
5167 case SVGA3D_RS_COORDINATETYPE: /* SVGA3dCoordinateType */
5168 Assert(pRenderState[i].uintValue == SVGA3D_COORDINATE_LEFTHANDED);
5169 /** @todo setup a view matrix to scale the world space by -1 in the z-direction for right handed coordinates. */
5170 /*
5171 renderState = D3DRS_COORDINATETYPE;
5172 val = pRenderState[i].uintValue;
5173 */
5174 break;
5175
5176 case SVGA3D_RS_FRONTWINDING: /* SVGA3dFrontWinding */
5177 Assert(pRenderState[i].uintValue == SVGA3D_FRONTWINDING_CW);
5178 /* Invert the selected mode because of y-inversion (?) */
5179 glFrontFace((pRenderState[i].uintValue != SVGA3D_FRONTWINDING_CW) ? GL_CW : GL_CCW);
5180 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5181 break;
5182
5183 case SVGA3D_RS_OUTPUTGAMMA: /* float */
5184 //AssertFailed();
5185 /*
5186 D3DRS_SRGBWRITEENABLE ??
5187 renderState = D3DRS_OUTPUTGAMMA;
5188 val = pRenderState[i].uintValue;
5189 */
5190 break;
5191
5192#if 0
5193
5194 case SVGA3D_RS_VERTEXMATERIALENABLE: /* SVGA3dBool */
5195 //AssertFailed();
5196 renderState = D3DRS_INDEXEDVERTEXBLENDENABLE; /* correct?? */
5197 val = pRenderState[i].uintValue;
5198 break;
5199
5200 case SVGA3D_RS_TEXTUREFACTOR: /* SVGA3dColor */
5201 renderState = D3DRS_TEXTUREFACTOR;
5202 val = pRenderState[i].uintValue;
5203 break;
5204
5205 case SVGA3D_RS_LOCALVIEWER: /* SVGA3dBool */
5206 renderState = D3DRS_LOCALVIEWER;
5207 val = pRenderState[i].uintValue;
5208 break;
5209
5210 case SVGA3D_RS_ZVISIBLE: /* SVGA3dBool */
5211 AssertFailed();
5212 /*
5213 renderState = D3DRS_ZVISIBLE;
5214 val = pRenderState[i].uintValue;
5215 */
5216 break;
5217
5218 case SVGA3D_RS_CLIPPING: /* SVGA3dBool */
5219 renderState = D3DRS_CLIPPING;
5220 val = pRenderState[i].uintValue;
5221 break;
5222
5223 case SVGA3D_RS_WRAP0: /* SVGA3dWrapFlags */
5224 glTexParameter GL_TEXTURE_WRAP_S
5225 Assert(SVGA3D_WRAPCOORD_3 == D3DWRAPCOORD_3);
5226 renderState = D3DRS_WRAP0;
5227 val = pRenderState[i].uintValue;
5228 break;
5229
5230 case SVGA3D_RS_WRAP1: /* SVGA3dWrapFlags */
5231 glTexParameter GL_TEXTURE_WRAP_T
5232 renderState = D3DRS_WRAP1;
5233 val = pRenderState[i].uintValue;
5234 break;
5235
5236 case SVGA3D_RS_WRAP2: /* SVGA3dWrapFlags */
5237 glTexParameter GL_TEXTURE_WRAP_R
5238 renderState = D3DRS_WRAP2;
5239 val = pRenderState[i].uintValue;
5240 break;
5241
5242
5243 case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */
5244 renderState = D3DRS_SEPARATEALPHABLENDENABLE;
5245 val = pRenderState[i].uintValue;
5246 break;
5247
5248
5249 case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation */
5250 renderState = D3DRS_BLENDOPALPHA;
5251 val = pRenderState[i].uintValue;
5252 break;
5253
5254 case SVGA3D_RS_TRANSPARENCYANTIALIAS: /* SVGA3dTransparencyAntialiasType */
5255 AssertFailed();
5256 /*
5257 renderState = D3DRS_TRANSPARENCYANTIALIAS;
5258 val = pRenderState[i].uintValue;
5259 */
5260 break;
5261
5262#endif
5263 default:
5264 AssertFailed();
5265 break;
5266 }
5267
5268 if (enableCap != ~(GLenum)0)
5269 {
5270 if (val)
5271 glEnable(enableCap);
5272 else
5273 glDisable(enableCap);
5274 }
5275 }
5276
5277 return VINF_SUCCESS;
5278}
5279
5280static DECLCALLBACK(int) vmsvga3dBackSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target)
5281{
5282 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5283
5284 AssertReturn(pState, VERR_NO_MEMORY);
5285 AssertReturn((unsigned)type < SVGA3D_RT_MAX, VERR_INVALID_PARAMETER);
5286
5287 LogFunc(("cid=%u type=%x sid=%u\n", cid, type, target.sid));
5288
5289 PVMSVGA3DCONTEXT pContext;
5290 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
5291 AssertRCReturn(rc, rc);
5292
5293 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5294
5295 /* Save for vm state save/restore. */
5296 pContext->state.aRenderTargets[type] = target.sid;
5297
5298 if (target.sid == SVGA3D_INVALID_ID)
5299 {
5300 /* Disable render target. */
5301 switch (type)
5302 {
5303 case SVGA3D_RT_DEPTH:
5304 case SVGA3D_RT_STENCIL:
5305 pState->ext.glFramebufferRenderbuffer(GL_FRAMEBUFFER, (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
5306 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5307 break;
5308
5309 case SVGA3D_RT_COLOR0:
5310 case SVGA3D_RT_COLOR1:
5311 case SVGA3D_RT_COLOR2:
5312 case SVGA3D_RT_COLOR3:
5313 case SVGA3D_RT_COLOR4:
5314 case SVGA3D_RT_COLOR5:
5315 case SVGA3D_RT_COLOR6:
5316 case SVGA3D_RT_COLOR7:
5317 pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + type - SVGA3D_RT_COLOR0, 0, 0, 0);
5318 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5319 break;
5320
5321 default:
5322 AssertFailedReturn(VERR_INVALID_PARAMETER);
5323 }
5324 return VINF_SUCCESS;
5325 }
5326
5327 PVMSVGA3DSURFACE pRenderTarget;
5328 rc = vmsvga3dSurfaceFromSid(pState, target.sid, &pRenderTarget);
5329 AssertRCReturn(rc, rc);
5330
5331 switch (type)
5332 {
5333 case SVGA3D_RT_DEPTH:
5334 case SVGA3D_RT_STENCIL:
5335#if 1
5336 /* A texture surface can be used as a render target to fill it and later on used as a texture. */
5337 if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID)
5338 {
5339 LogFunc(("create depth texture to be used as render target; surface id=%x type=%d format=%d -> create texture\n",
5340 target.sid, pRenderTarget->surfaceFlags, pRenderTarget->format));
5341 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget);
5342 AssertRCReturn(rc, rc);
5343 }
5344
5345 AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER);
5346 Assert(!pRenderTarget->fDirty);
5347
5348 pRenderTarget->surfaceFlags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
5349
5350 pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER,
5351 (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT,
5352 GL_TEXTURE_2D, pRenderTarget->oglId.texture, target.mipmap);
5353 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5354#else
5355 AssertReturn(target.mipmap == 0, VERR_INVALID_PARAMETER);
5356 if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID)
5357 {
5358 Log(("vmsvga3dSetRenderTarget: create renderbuffer to be used as render target; surface id=%x type=%d format=%d\n", target.sid, pRenderTarget->surfaceFlags, pRenderTarget->internalFormatGL));
5359 pContext = &pState->SharedCtx;
5360 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5361
5362 pState->ext.glGenRenderbuffers(1, &pRenderTarget->oglId.renderbuffer);
5363 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5364 pSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_RENDERBUFFER;
5365
5366 pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer);
5367 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5368
5369 pState->ext.glRenderbufferStorage(GL_RENDERBUFFER,
5370 pRenderTarget->internalFormatGL,
5371 pRenderTarget->paMipmapLevels[0].mipmapSize.width,
5372 pRenderTarget->paMipmapLevels[0].mipmapSize.height);
5373 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5374
5375 pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, OPENGL_INVALID_ID);
5376 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5377
5378 pContext = pState->papContexts[cid];
5379 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5380 }
5381
5382 pState->ext.glBindRenderbuffer(GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer);
5383 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5384 Assert(!pRenderTarget->fDirty);
5385 AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER);
5386
5387 pRenderTarget->surfaceFlags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
5388
5389 pState->ext.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
5390 (type == SVGA3D_RT_DEPTH) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT,
5391 GL_RENDERBUFFER, pRenderTarget->oglId.renderbuffer);
5392 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5393#endif
5394 break;
5395
5396 case SVGA3D_RT_COLOR0:
5397 case SVGA3D_RT_COLOR1:
5398 case SVGA3D_RT_COLOR2:
5399 case SVGA3D_RT_COLOR3:
5400 case SVGA3D_RT_COLOR4:
5401 case SVGA3D_RT_COLOR5:
5402 case SVGA3D_RT_COLOR6:
5403 case SVGA3D_RT_COLOR7:
5404 {
5405 /* A texture surface can be used as a render target to fill it and later on used as a texture. */
5406 if (pRenderTarget->oglId.texture == OPENGL_INVALID_ID)
5407 {
5408 Log(("vmsvga3dSetRenderTarget: create texture to be used as render target; surface id=%x type=%d format=%d -> create texture\n", target.sid, pRenderTarget->surfaceFlags, pRenderTarget->format));
5409 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pRenderTarget);
5410 AssertRCReturn(rc, rc);
5411 }
5412
5413 AssertReturn(pRenderTarget->oglId.texture != OPENGL_INVALID_ID, VERR_INVALID_PARAMETER);
5414 Assert(!pRenderTarget->fDirty);
5415
5416 pRenderTarget->surfaceFlags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
5417
5418 GLenum textarget;
5419 if (pRenderTarget->surfaceFlags & SVGA3D_SURFACE_CUBEMAP)
5420 textarget = vmsvga3dCubemapFaceFromIndex(target.face);
5421 else
5422 textarget = GL_TEXTURE_2D;
5423 pState->ext.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + type - SVGA3D_RT_COLOR0,
5424 textarget, pRenderTarget->oglId.texture, target.mipmap);
5425 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5426
5427#ifdef DEBUG
5428 GLenum status = pState->ext.glCheckFramebufferStatus(GL_FRAMEBUFFER);
5429 if (status != GL_FRAMEBUFFER_COMPLETE)
5430 Log(("vmsvga3dSetRenderTarget: WARNING: glCheckFramebufferStatus returned %x\n", status));
5431#endif
5432 /** @todo use glDrawBuffers too? */
5433 break;
5434 }
5435
5436 default:
5437 AssertFailedReturn(VERR_INVALID_PARAMETER);
5438 }
5439
5440 return VINF_SUCCESS;
5441}
5442
5443#if 0
5444/**
5445 * Convert SVGA texture combiner value to its D3D equivalent
5446 */
5447static DWORD vmsvga3dTextureCombiner2D3D(uint32_t value)
5448{
5449 switch (value)
5450 {
5451 case SVGA3D_TC_DISABLE:
5452 return D3DTOP_DISABLE;
5453 case SVGA3D_TC_SELECTARG1:
5454 return D3DTOP_SELECTARG1;
5455 case SVGA3D_TC_SELECTARG2:
5456 return D3DTOP_SELECTARG2;
5457 case SVGA3D_TC_MODULATE:
5458 return D3DTOP_MODULATE;
5459 case SVGA3D_TC_ADD:
5460 return D3DTOP_ADD;
5461 case SVGA3D_TC_ADDSIGNED:
5462 return D3DTOP_ADDSIGNED;
5463 case SVGA3D_TC_SUBTRACT:
5464 return D3DTOP_SUBTRACT;
5465 case SVGA3D_TC_BLENDTEXTUREALPHA:
5466 return D3DTOP_BLENDTEXTUREALPHA;
5467 case SVGA3D_TC_BLENDDIFFUSEALPHA:
5468 return D3DTOP_BLENDDIFFUSEALPHA;
5469 case SVGA3D_TC_BLENDCURRENTALPHA:
5470 return D3DTOP_BLENDCURRENTALPHA;
5471 case SVGA3D_TC_BLENDFACTORALPHA:
5472 return D3DTOP_BLENDFACTORALPHA;
5473 case SVGA3D_TC_MODULATE2X:
5474 return D3DTOP_MODULATE2X;
5475 case SVGA3D_TC_MODULATE4X:
5476 return D3DTOP_MODULATE4X;
5477 case SVGA3D_TC_DSDT:
5478 AssertFailed(); /** @todo ??? */
5479 return D3DTOP_DISABLE;
5480 case SVGA3D_TC_DOTPRODUCT3:
5481 return D3DTOP_DOTPRODUCT3;
5482 case SVGA3D_TC_BLENDTEXTUREALPHAPM:
5483 return D3DTOP_BLENDTEXTUREALPHAPM;
5484 case SVGA3D_TC_ADDSIGNED2X:
5485 return D3DTOP_ADDSIGNED2X;
5486 case SVGA3D_TC_ADDSMOOTH:
5487 return D3DTOP_ADDSMOOTH;
5488 case SVGA3D_TC_PREMODULATE:
5489 return D3DTOP_PREMODULATE;
5490 case SVGA3D_TC_MODULATEALPHA_ADDCOLOR:
5491 return D3DTOP_MODULATEALPHA_ADDCOLOR;
5492 case SVGA3D_TC_MODULATECOLOR_ADDALPHA:
5493 return D3DTOP_MODULATECOLOR_ADDALPHA;
5494 case SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR:
5495 return D3DTOP_MODULATEINVALPHA_ADDCOLOR;
5496 case SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA:
5497 return D3DTOP_MODULATEINVCOLOR_ADDALPHA;
5498 case SVGA3D_TC_BUMPENVMAPLUMINANCE:
5499 return D3DTOP_BUMPENVMAPLUMINANCE;
5500 case SVGA3D_TC_MULTIPLYADD:
5501 return D3DTOP_MULTIPLYADD;
5502 case SVGA3D_TC_LERP:
5503 return D3DTOP_LERP;
5504 default:
5505 AssertFailed();
5506 return D3DTOP_DISABLE;
5507 }
5508}
5509
5510/**
5511 * Convert SVGA texture arg data value to its D3D equivalent
5512 */
5513static DWORD vmsvga3dTextureArgData2D3D(uint32_t value)
5514{
5515 switch (value)
5516 {
5517 case SVGA3D_TA_CONSTANT:
5518 return D3DTA_CONSTANT;
5519 case SVGA3D_TA_PREVIOUS:
5520 return D3DTA_CURRENT; /* current = previous */
5521 case SVGA3D_TA_DIFFUSE:
5522 return D3DTA_DIFFUSE;
5523 case SVGA3D_TA_TEXTURE:
5524 return D3DTA_TEXTURE;
5525 case SVGA3D_TA_SPECULAR:
5526 return D3DTA_SPECULAR;
5527 default:
5528 AssertFailed();
5529 return 0;
5530 }
5531}
5532
5533/**
5534 * Convert SVGA texture transform flag value to its D3D equivalent
5535 */
5536static DWORD vmsvga3dTextTransformFlags2D3D(uint32_t value)
5537{
5538 switch (value)
5539 {
5540 case SVGA3D_TEX_TRANSFORM_OFF:
5541 return D3DTTFF_DISABLE;
5542 case SVGA3D_TEX_TRANSFORM_S:
5543 return D3DTTFF_COUNT1; /** @todo correct? */
5544 case SVGA3D_TEX_TRANSFORM_T:
5545 return D3DTTFF_COUNT2; /** @todo correct? */
5546 case SVGA3D_TEX_TRANSFORM_R:
5547 return D3DTTFF_COUNT3; /** @todo correct? */
5548 case SVGA3D_TEX_TRANSFORM_Q:
5549 return D3DTTFF_COUNT4; /** @todo correct? */
5550 case SVGA3D_TEX_PROJECTED:
5551 return D3DTTFF_PROJECTED;
5552 default:
5553 AssertFailed();
5554 return 0;
5555 }
5556}
5557#endif
5558
5559static GLenum vmsvga3dTextureAddress2OGL(SVGA3dTextureAddress value)
5560{
5561 switch (value)
5562 {
5563 case SVGA3D_TEX_ADDRESS_WRAP:
5564 return GL_REPEAT;
5565 case SVGA3D_TEX_ADDRESS_MIRROR:
5566 return GL_MIRRORED_REPEAT;
5567 case SVGA3D_TEX_ADDRESS_CLAMP:
5568 return GL_CLAMP_TO_EDGE;
5569 case SVGA3D_TEX_ADDRESS_BORDER:
5570 return GL_CLAMP_TO_BORDER;
5571 case SVGA3D_TEX_ADDRESS_MIRRORONCE:
5572 AssertFailed();
5573 return GL_CLAMP_TO_EDGE_SGIS; /** @todo correct? */
5574
5575 case SVGA3D_TEX_ADDRESS_EDGE:
5576 case SVGA3D_TEX_ADDRESS_INVALID:
5577 default:
5578 AssertFailed();
5579 return GL_REPEAT; /* default */
5580 }
5581}
5582
5583static GLenum vmsvga3dTextureFilter2OGL(SVGA3dTextureFilter value)
5584{
5585 switch (value)
5586 {
5587 case SVGA3D_TEX_FILTER_NONE:
5588 case SVGA3D_TEX_FILTER_LINEAR:
5589 case SVGA3D_TEX_FILTER_ANISOTROPIC: /* Anisotropic filtering is controlled by SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL */
5590 return GL_LINEAR;
5591 case SVGA3D_TEX_FILTER_NEAREST:
5592 return GL_NEAREST;
5593 case SVGA3D_TEX_FILTER_FLATCUBIC: // Deprecated, not implemented
5594 case SVGA3D_TEX_FILTER_GAUSSIANCUBIC: // Deprecated, not implemented
5595 case SVGA3D_TEX_FILTER_PYRAMIDALQUAD: // Not currently implemented
5596 case SVGA3D_TEX_FILTER_GAUSSIANQUAD: // Not currently implemented
5597 default:
5598 AssertFailed();
5599 return GL_LINEAR; /* default */
5600 }
5601}
5602
5603uint32_t vmsvga3dSVGA3dColor2RGBA(SVGA3dColor value)
5604{
5605 /* flip the red and blue bytes */
5606 uint8_t blue = value & 0xff;
5607 uint8_t red = (value >> 16) & 0xff;
5608 return (value & 0xff00ff00) | red | (blue << 16);
5609}
5610
5611static DECLCALLBACK(int) vmsvga3dBackSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState)
5612{
5613 GLenum val = ~(GLenum)0; /* Shut up MSC. */
5614 GLenum currentStage = ~(GLenum)0;
5615 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5616 AssertReturn(pState, VERR_NO_MEMORY);
5617
5618 Log(("vmsvga3dSetTextureState %x cTextureState=%d\n", cid, cTextureStates));
5619
5620 PVMSVGA3DCONTEXT pContext;
5621 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
5622 AssertRCReturn(rc, rc);
5623
5624 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5625
5626 /* Which texture is active for the current stage. Needed to use right OpenGL target when setting parameters. */
5627 PVMSVGA3DSURFACE pCurrentTextureSurface = NULL;
5628
5629 for (uint32_t i = 0; i < cTextureStates; ++i)
5630 {
5631 GLenum textureType = ~(GLenum)0;
5632#if 0
5633 GLenum samplerType = ~(GLenum)0;
5634#endif
5635
5636 LogFunc(("cid=%u stage=%d type=%s (%x) val=%x\n",
5637 cid, pTextureState[i].stage, vmsvga3dTextureStateToString(pTextureState[i].name), pTextureState[i].name, pTextureState[i].value));
5638
5639 /* Record the texture state for vm state saving. */
5640 if ( pTextureState[i].stage < RT_ELEMENTS(pContext->state.aTextureStates)
5641 && (unsigned)pTextureState[i].name < RT_ELEMENTS(pContext->state.aTextureStates[0]))
5642 {
5643 pContext->state.aTextureStates[pTextureState[i].stage][pTextureState[i].name] = pTextureState[i];
5644 }
5645
5646 /* Activate the right texture unit for subsequent texture state changes. */
5647 if (pTextureState[i].stage != currentStage || i == 0)
5648 {
5649 /** @todo Is this the appropriate limit for all kinds of textures? It is the
5650 * size of aSidActiveTextures and for binding/unbinding we cannot exceed it. */
5651 if (pTextureState[i].stage < RT_ELEMENTS(pContext->state.aTextureStates))
5652 {
5653 pState->ext.glActiveTexture(GL_TEXTURE0 + pTextureState[i].stage);
5654 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5655 currentStage = pTextureState[i].stage;
5656 }
5657 else
5658 {
5659 AssertMsgFailed(("pTextureState[%d].stage=%#x name=%#x\n", i, pTextureState[i].stage, pTextureState[i].name));
5660 continue;
5661 }
5662
5663 if (pContext->aSidActiveTextures[currentStage] != SVGA3D_INVALID_ID)
5664 {
5665 rc = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[currentStage], &pCurrentTextureSurface);
5666 AssertRCReturn(rc, rc);
5667 }
5668 else
5669 pCurrentTextureSurface = NULL; /* Make sure that no stale pointer is used. */
5670 }
5671
5672 switch (pTextureState[i].name)
5673 {
5674 case SVGA3D_TS_BUMPENVMAT00: /* float */
5675 case SVGA3D_TS_BUMPENVMAT01: /* float */
5676 case SVGA3D_TS_BUMPENVMAT10: /* float */
5677 case SVGA3D_TS_BUMPENVMAT11: /* float */
5678 case SVGA3D_TS_BUMPENVLSCALE: /* float */
5679 case SVGA3D_TS_BUMPENVLOFFSET: /* float */
5680 Log(("vmsvga3dSetTextureState: bump mapping texture options not supported!!\n"));
5681 break;
5682
5683 case SVGA3D_TS_COLOROP: /* SVGA3dTextureCombiner */
5684 case SVGA3D_TS_COLORARG0: /* SVGA3dTextureArgData */
5685 case SVGA3D_TS_COLORARG1: /* SVGA3dTextureArgData */
5686 case SVGA3D_TS_COLORARG2: /* SVGA3dTextureArgData */
5687 case SVGA3D_TS_ALPHAOP: /* SVGA3dTextureCombiner */
5688 case SVGA3D_TS_ALPHAARG0: /* SVGA3dTextureArgData */
5689 case SVGA3D_TS_ALPHAARG1: /* SVGA3dTextureArgData */
5690 case SVGA3D_TS_ALPHAARG2: /* SVGA3dTextureArgData */
5691 /** @todo not used by MesaGL */
5692 Log(("vmsvga3dSetTextureState: colorop/alphaop not yet supported!!\n"));
5693 break;
5694#if 0
5695
5696 case SVGA3D_TS_TEXCOORDINDEX: /* uint32_t */
5697 textureType = D3DTSS_TEXCOORDINDEX;
5698 val = pTextureState[i].value;
5699 break;
5700
5701 case SVGA3D_TS_TEXTURETRANSFORMFLAGS: /* SVGA3dTexTransformFlags */
5702 textureType = D3DTSS_TEXTURETRANSFORMFLAGS;
5703 val = vmsvga3dTextTransformFlags2D3D(pTextureState[i].value);
5704 break;
5705#endif
5706
5707 case SVGA3D_TS_BIND_TEXTURE: /* SVGA3dSurfaceId */
5708 {
5709 uint32_t const sid = pTextureState[i].value;
5710
5711 Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%u replacing sid=%u\n",
5712 currentStage, sid, pContext->aSidActiveTextures[currentStage]));
5713
5714 /* Only if texture actually changed. */ /// @todo needs testing.
5715 if (pContext->aSidActiveTextures[currentStage] != sid)
5716 {
5717 if (pCurrentTextureSurface)
5718 {
5719 /* Unselect the currently associated texture. */
5720 glBindTexture(pCurrentTextureSurface->targetGL, 0);
5721 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5722
5723 if (currentStage < 8)
5724 {
5725 /* Necessary for the fixed pipeline. */
5726 glDisable(pCurrentTextureSurface->targetGL);
5727 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5728 }
5729
5730 pCurrentTextureSurface = NULL;
5731 }
5732
5733 if (sid == SVGA3D_INVALID_ID)
5734 {
5735 Assert(pCurrentTextureSurface == NULL);
5736 }
5737 else
5738 {
5739 PVMSVGA3DSURFACE pSurface;
5740 rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
5741 AssertRCReturn(rc, rc);
5742
5743 Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%u (%d,%d) replacing sid=%u\n",
5744 currentStage, sid, pSurface->paMipmapLevels[0].mipmapSize.width,
5745 pSurface->paMipmapLevels[0].mipmapSize.height, pContext->aSidActiveTextures[currentStage]));
5746
5747 if (pSurface->oglId.texture == OPENGL_INVALID_ID)
5748 {
5749 Log(("CreateTexture (%d,%d) levels=%d\n",
5750 pSurface->paMipmapLevels[0].mipmapSize.width, pSurface->paMipmapLevels[0].mipmapSize.height, pSurface->cLevels));
5751 rc = vmsvga3dBackCreateTexture(pThisCC, pContext, cid, pSurface);
5752 AssertRCReturn(rc, rc);
5753 }
5754
5755 glBindTexture(pSurface->targetGL, pSurface->oglId.texture);
5756 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5757
5758 if (currentStage < 8)
5759 {
5760 /* Necessary for the fixed pipeline. */
5761 glEnable(pSurface->targetGL);
5762 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5763 }
5764
5765 /* Remember the currently active texture. */
5766 pCurrentTextureSurface = pSurface;
5767
5768 /* Recreate the texture state as glBindTexture resets them all (sigh). */
5769 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); iStage++)
5770 {
5771 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); j++)
5772 {
5773 SVGA3dTextureState *pTextureStateIter = &pContext->state.aTextureStates[iStage][j];
5774
5775 if ( pTextureStateIter->name != SVGA3D_TS_INVALID
5776 && pTextureStateIter->name != SVGA3D_TS_BIND_TEXTURE)
5777 vmsvga3dBackSetTextureState(pThisCC, pContext->id, 1, pTextureStateIter);
5778 }
5779 }
5780 }
5781
5782 pContext->aSidActiveTextures[currentStage] = sid;
5783 }
5784
5785 /* Finished; continue with the next one. */
5786 continue;
5787 }
5788
5789 case SVGA3D_TS_ADDRESSW: /* SVGA3dTextureAddress */
5790 textureType = GL_TEXTURE_WRAP_R; /* R = W */
5791 val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value);
5792 break;
5793
5794 case SVGA3D_TS_ADDRESSU: /* SVGA3dTextureAddress */
5795 textureType = GL_TEXTURE_WRAP_S; /* S = U */
5796 val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value);
5797 break;
5798
5799 case SVGA3D_TS_ADDRESSV: /* SVGA3dTextureAddress */
5800 textureType = GL_TEXTURE_WRAP_T; /* T = V */
5801 val = vmsvga3dTextureAddress2OGL((SVGA3dTextureAddress)pTextureState[i].value);
5802 break;
5803
5804 case SVGA3D_TS_MIPFILTER: /* SVGA3dTextureFilter */
5805 case SVGA3D_TS_MINFILTER: /* SVGA3dTextureFilter */
5806 {
5807 uint32_t mipFilter = pContext->state.aTextureStates[currentStage][SVGA3D_TS_MIPFILTER].value;
5808 uint32_t minFilter = pContext->state.aTextureStates[currentStage][SVGA3D_TS_MINFILTER].value;
5809
5810 /* If SVGA3D_TS_MIPFILTER is set to NONE, then use SVGA3D_TS_MIPFILTER, otherwise SVGA3D_TS_MIPFILTER enables mipmap minification. */
5811 textureType = GL_TEXTURE_MIN_FILTER;
5812 if (mipFilter != SVGA3D_TEX_FILTER_NONE)
5813 {
5814 if (minFilter == SVGA3D_TEX_FILTER_NEAREST)
5815 {
5816 if (mipFilter == SVGA3D_TEX_FILTER_LINEAR)
5817 val = GL_NEAREST_MIPMAP_LINEAR;
5818 else
5819 val = GL_NEAREST_MIPMAP_NEAREST;
5820 }
5821 else
5822 {
5823 if (mipFilter == SVGA3D_TEX_FILTER_LINEAR)
5824 val = GL_LINEAR_MIPMAP_LINEAR;
5825 else
5826 val = GL_LINEAR_MIPMAP_NEAREST;
5827 }
5828 }
5829 else
5830 val = vmsvga3dTextureFilter2OGL((SVGA3dTextureFilter)minFilter);
5831 break;
5832 }
5833
5834 case SVGA3D_TS_MAGFILTER: /* SVGA3dTextureFilter */
5835 textureType = GL_TEXTURE_MAG_FILTER;
5836 val = vmsvga3dTextureFilter2OGL((SVGA3dTextureFilter)pTextureState[i].value);
5837 Assert(val == GL_NEAREST || val == GL_LINEAR);
5838 break;
5839
5840 case SVGA3D_TS_BORDERCOLOR: /* SVGA3dColor */
5841 {
5842 GLfloat color[4]; /* red, green, blue, alpha */
5843 vmsvgaColor2GLFloatArray(pTextureState[i].value, &color[0], &color[1], &color[2], &color[3]);
5844
5845 GLenum targetGL;
5846 if (pCurrentTextureSurface)
5847 targetGL = pCurrentTextureSurface->targetGL;
5848 else
5849 {
5850 /* No texture bound, assume 2D. */
5851 targetGL = GL_TEXTURE_2D;
5852 }
5853
5854 glTexParameterfv(targetGL, GL_TEXTURE_BORDER_COLOR, color); /* Identical; default 0.0 identical too */
5855 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5856 break;
5857 }
5858
5859 case SVGA3D_TS_TEXTURE_LOD_BIAS: /* float */
5860 {
5861 GLenum targetGL;
5862 if (pCurrentTextureSurface)
5863 targetGL = pCurrentTextureSurface->targetGL;
5864 else
5865 {
5866 /* No texture bound, assume 2D. */
5867 targetGL = GL_TEXTURE_2D;
5868 }
5869
5870 glTexParameterf(targetGL, GL_TEXTURE_LOD_BIAS, pTextureState[i].floatValue); /* Identical; default 0.0 identical too */
5871 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5872 break;
5873 }
5874
5875 case SVGA3D_TS_TEXTURE_MIPMAP_LEVEL: /* uint32_t */
5876 textureType = GL_TEXTURE_BASE_LEVEL;
5877 val = pTextureState[i].value;
5878 break;
5879
5880 case SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL: /* uint32_t */
5881 if (pState->caps.fTextureFilterAnisotropicSupported)
5882 {
5883 textureType = GL_TEXTURE_MAX_ANISOTROPY_EXT;
5884 val = RT_MIN((GLint)pTextureState[i].value, pState->caps.maxTextureAnisotropy);
5885 } /* otherwise ignore. */
5886 break;
5887
5888#if 0
5889 case SVGA3D_TS_GAMMA: /* float */
5890 samplerType = D3DSAMP_SRGBTEXTURE;
5891 /* Boolean in D3D */
5892 if (pTextureState[i].floatValue == 1.0f)
5893 val = FALSE;
5894 else
5895 val = TRUE;
5896 break;
5897#endif
5898 /* Internal commands, that don't map directly to the SetTextureStageState API. */
5899 case SVGA3D_TS_TEXCOORDGEN: /* SVGA3dTextureCoordGen */
5900 AssertFailed();
5901 break;
5902
5903 default:
5904 //AssertFailed();
5905 break;
5906 }
5907
5908 if (textureType != ~(GLenum)0)
5909 {
5910 GLenum targetGL;
5911 if (pCurrentTextureSurface)
5912 targetGL = pCurrentTextureSurface->targetGL;
5913 else
5914 {
5915 /* No texture bound, assume 2D. */
5916 targetGL = GL_TEXTURE_2D;
5917 }
5918
5919 switch (pTextureState[i].name)
5920 {
5921 case SVGA3D_TS_MINFILTER:
5922 case SVGA3D_TS_MAGFILTER:
5923 {
5924 if (pState->caps.fTextureFilterAnisotropicSupported)
5925 {
5926 uint32_t const anisotropyLevel = (SVGA3dTextureFilter)pTextureState[i].value == SVGA3D_TEX_FILTER_ANISOTROPIC
5927 ? RT_MAX(1, pContext->state.aTextureStates[currentStage][SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL].value)
5928 : 1;
5929 glTexParameteri(targetGL, GL_TEXTURE_MAX_ANISOTROPY_EXT, RT_MIN((GLint)anisotropyLevel, pState->caps.maxTextureAnisotropy));
5930 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5931 }
5932 } break;
5933
5934 default: break;
5935 }
5936
5937 glTexParameteri(targetGL, textureType, val);
5938 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5939 }
5940 }
5941
5942 return VINF_SUCCESS;
5943}
5944
5945static DECLCALLBACK(int) vmsvga3dBackSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial)
5946{
5947 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5948 AssertReturn(pState, VERR_NO_MEMORY);
5949
5950 LogFunc(("cid=%u face %d\n", cid, face));
5951
5952 PVMSVGA3DCONTEXT pContext;
5953 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
5954 AssertRCReturn(rc, rc);
5955
5956 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
5957
5958 GLenum oglFace;
5959 switch (face)
5960 {
5961 case SVGA3D_FACE_NONE:
5962 case SVGA3D_FACE_FRONT:
5963 oglFace = GL_FRONT;
5964 break;
5965
5966 case SVGA3D_FACE_BACK:
5967 oglFace = GL_BACK;
5968 break;
5969
5970 case SVGA3D_FACE_FRONT_BACK:
5971 oglFace = GL_FRONT_AND_BACK;
5972 break;
5973
5974 default:
5975 AssertFailedReturn(VERR_INVALID_PARAMETER);
5976 }
5977
5978 /* Save for vm state save/restore. */
5979 pContext->state.aMaterial[face].fValid = true;
5980 pContext->state.aMaterial[face].material = *pMaterial;
5981 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_MATERIAL;
5982
5983 glMaterialfv(oglFace, GL_DIFFUSE, pMaterial->diffuse);
5984 glMaterialfv(oglFace, GL_AMBIENT, pMaterial->ambient);
5985 glMaterialfv(oglFace, GL_SPECULAR, pMaterial->specular);
5986 glMaterialfv(oglFace, GL_EMISSION, pMaterial->emissive);
5987 glMaterialfv(oglFace, GL_SHININESS, &pMaterial->shininess);
5988 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
5989
5990 return VINF_SUCCESS;
5991}
5992
5993/** @todo Move into separate library as we are using logic from Wine here. */
5994static DECLCALLBACK(int) vmsvga3dBackSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData)
5995{
5996 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
5997 AssertReturn(pState, VERR_NO_MEMORY);
5998
5999 LogFunc(("vmsvga3dSetLightData cid=%u index=%d type=%d\n", cid, index, pData->type));
6000 ASSERT_GUEST_RETURN(index < SVGA3D_MAX_LIGHTS, VERR_INVALID_PARAMETER);
6001
6002 PVMSVGA3DCONTEXT pContext;
6003 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6004 AssertRCReturn(rc, rc);
6005
6006 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6007
6008 /* Store for vm state save/restore */
6009 pContext->state.aLightData[index].fValidData = true;
6010 pContext->state.aLightData[index].data = *pData;
6011
6012 if ( pData->attenuation0 < 0.0f
6013 || pData->attenuation1 < 0.0f
6014 || pData->attenuation2 < 0.0f)
6015 {
6016 Log(("vmsvga3dSetLightData: invalid negative attenuation values!!\n"));
6017 return VINF_SUCCESS; /* ignore; could crash the GL driver */
6018 }
6019
6020 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d */
6021 glMatrixMode(GL_MODELVIEW);
6022 glPushMatrix();
6023 glLoadMatrixf(pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix);
6024
6025 glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, pData->diffuse);
6026 glLightfv(GL_LIGHT0 + index, GL_SPECULAR, pData->specular);
6027 glLightfv(GL_LIGHT0 + index, GL_AMBIENT, pData->ambient);
6028
6029 float QuadAttenuation;
6030 if (pData->range * pData->range >= FLT_MIN)
6031 QuadAttenuation = 1.4f / (pData->range * pData->range);
6032 else
6033 QuadAttenuation = 0.0f;
6034
6035 switch (pData->type)
6036 {
6037 case SVGA3D_LIGHTTYPE_POINT:
6038 {
6039 GLfloat position[4];
6040
6041 position[0] = pData->position[0];
6042 position[1] = pData->position[1];
6043 position[2] = pData->position[2];
6044 position[3] = 1.0f;
6045
6046 glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
6047 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6048
6049 glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
6050 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6051
6052 /* Attenuation - Are these right? guessing... */
6053 glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, pData->attenuation0);
6054 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6055
6056 glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, pData->attenuation1);
6057 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6058
6059 glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, (QuadAttenuation < pData->attenuation2) ? pData->attenuation2 : QuadAttenuation);
6060 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6061
6062 /** @todo range */
6063 break;
6064 }
6065
6066 case SVGA3D_LIGHTTYPE_SPOT1:
6067 {
6068 GLfloat exponent;
6069 GLfloat position[4];
6070 const GLfloat pi = 4.0f * atanf(1.0f);
6071
6072 position[0] = pData->position[0];
6073 position[1] = pData->position[1];
6074 position[2] = pData->position[2];
6075 position[3] = 1.0f;
6076
6077 glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
6078 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6079
6080 position[0] = pData->direction[0];
6081 position[1] = pData->direction[1];
6082 position[2] = pData->direction[2];
6083 position[3] = 1.0f;
6084
6085 glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, position);
6086 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6087
6088 /*
6089 * opengl-ish and d3d-ish spot lights use too different models for the
6090 * light "intensity" as a function of the angle towards the main light direction,
6091 * so we only can approximate very roughly.
6092 * however spot lights are rather rarely used in games (if ever used at all).
6093 * furthermore if still used, probably nobody pays attention to such details.
6094 */
6095 if (pData->falloff == 0)
6096 {
6097 /* Falloff = 0 is easy, because d3d's and opengl's spot light equations have the
6098 * falloff resp. exponent parameter as an exponent, so the spot light lighting
6099 * will always be 1.0 for both of them, and we don't have to care for the
6100 * rest of the rather complex calculation
6101 */
6102 exponent = 0.0f;
6103 }
6104 else
6105 {
6106 float rho = pData->theta + (pData->phi - pData->theta) / (2 * pData->falloff);
6107 if (rho < 0.0001f)
6108 rho = 0.0001f;
6109 exponent = -0.3f/log(cos(rho/2));
6110 }
6111 if (exponent > 128.0f)
6112 exponent = 128.0f;
6113
6114 glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, exponent);
6115 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6116
6117 glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, pData->phi * 90.0 / pi);
6118 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6119
6120 /* Attenuation - Are these right? guessing... */
6121 glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, pData->attenuation0);
6122 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6123
6124 glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, pData->attenuation1);
6125 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6126
6127 glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, (QuadAttenuation < pData->attenuation2) ? pData->attenuation2 : QuadAttenuation);
6128 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6129
6130 /** @todo range */
6131 break;
6132 }
6133
6134 case SVGA3D_LIGHTTYPE_DIRECTIONAL:
6135 {
6136 GLfloat position[4];
6137
6138 position[0] = -pData->direction[0];
6139 position[1] = -pData->direction[1];
6140 position[2] = -pData->direction[2];
6141 position[3] = 0.0f;
6142
6143 glLightfv(GL_LIGHT0 + index, GL_POSITION, position); /* Note gl uses w position of 0 for direction! */
6144 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6145
6146 glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
6147 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6148
6149 glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, 0.0f);
6150 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6151 break;
6152 }
6153
6154 case SVGA3D_LIGHTTYPE_SPOT2:
6155 default:
6156 Log(("Unsupported light type!!\n"));
6157 rc = VERR_INVALID_PARAMETER;
6158 break;
6159 }
6160
6161 /* Restore the modelview matrix */
6162 glPopMatrix();
6163
6164 return rc;
6165}
6166
6167static DECLCALLBACK(int) vmsvga3dBackSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled)
6168{
6169 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6170 AssertReturn(pState, VERR_NO_MEMORY);
6171
6172 LogFunc(("cid=%u %d -> %d\n", cid, index, enabled));
6173
6174 PVMSVGA3DCONTEXT pContext;
6175 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6176 AssertRCReturn(rc, rc);
6177
6178 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6179
6180 /* Store for vm state save/restore */
6181 if (index < SVGA3D_MAX_LIGHTS)
6182 pContext->state.aLightData[index].fEnabled = !!enabled;
6183 else
6184 AssertFailed();
6185
6186 if (enabled)
6187 {
6188 if (index < SVGA3D_MAX_LIGHTS)
6189 {
6190 /* Load the default settings if none have been set yet. */
6191 if (!pContext->state.aLightData[index].fValidData)
6192 vmsvga3dBackSetLightData(pThisCC, cid, index, (SVGA3dLightData *)&vmsvga3d_default_light);
6193 }
6194 glEnable(GL_LIGHT0 + index);
6195 }
6196 else
6197 glDisable(GL_LIGHT0 + index);
6198
6199 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6200 return VINF_SUCCESS;
6201}
6202
6203static DECLCALLBACK(int) vmsvga3dBackSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)
6204{
6205 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6206 AssertReturn(pState, VERR_NO_MEMORY);
6207
6208 Log(("vmsvga3dSetViewPort cid=%u (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h));
6209
6210 PVMSVGA3DCONTEXT pContext;
6211 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6212 AssertRCReturn(rc, rc);
6213
6214 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6215
6216 /* Save for vm state save/restore. */
6217 pContext->state.RectViewPort = *pRect;
6218 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VIEWPORT;
6219
6220 /** @todo y-inversion for partial viewport coordinates? */
6221 glViewport(pRect->x, pRect->y, pRect->w, pRect->h);
6222 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6223
6224 /* Reset the projection matrix as that relies on the viewport setting. */
6225 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].fValid == true)
6226 vmsvga3dBackSetTransform(pThisCC, cid, SVGA3D_TRANSFORM_PROJECTION,
6227 pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].matrix);
6228 else
6229 {
6230 float matrix[16];
6231
6232 /* identity matrix if no matrix set. */
6233 memset(matrix, 0, sizeof(matrix));
6234 matrix[0] = 1.0;
6235 matrix[5] = 1.0;
6236 matrix[10] = 1.0;
6237 matrix[15] = 1.0;
6238 vmsvga3dBackSetTransform(pThisCC, cid, SVGA3D_TRANSFORM_PROJECTION, matrix);
6239 }
6240
6241 return VINF_SUCCESS;
6242}
6243
6244static DECLCALLBACK(int) vmsvga3dBackSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4])
6245{
6246 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6247 AssertReturn(pState, VERR_NO_MEMORY);
6248 double oglPlane[4];
6249
6250 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)));
6251 AssertReturn(index < SVGA3D_NUM_CLIPPLANES, VERR_INVALID_PARAMETER);
6252
6253 PVMSVGA3DCONTEXT pContext;
6254 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6255 AssertRCReturn(rc, rc);
6256
6257 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6258
6259 /* Store for vm state save/restore. */
6260 pContext->state.aClipPlane[index].fValid = true;
6261 memcpy(pContext->state.aClipPlane[index].plane, plane, sizeof(pContext->state.aClipPlane[index].plane));
6262
6263 /** @todo clip plane affected by model view in OpenGL & view in D3D + vertex shader -> not transformed (see Wine; state.c clipplane) */
6264 oglPlane[0] = (double)plane[0];
6265 oglPlane[1] = (double)plane[1];
6266 oglPlane[2] = (double)plane[2];
6267 oglPlane[3] = (double)plane[3];
6268
6269 glClipPlane(GL_CLIP_PLANE0 + index, oglPlane);
6270 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6271
6272 return VINF_SUCCESS;
6273}
6274
6275static DECLCALLBACK(int) vmsvga3dBackSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)
6276{
6277 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6278 AssertReturn(pState, VERR_NO_MEMORY);
6279
6280 Log(("vmsvga3dSetScissorRect cid=%u (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h));
6281
6282 PVMSVGA3DCONTEXT pContext;
6283 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6284 AssertRCReturn(rc, rc);
6285
6286 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6287
6288 /* Store for vm state save/restore. */
6289 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_SCISSORRECT;
6290 pContext->state.RectScissor = *pRect;
6291
6292 glScissor(pRect->x, pRect->y, pRect->w, pRect->h);
6293 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6294
6295 return VINF_SUCCESS;
6296}
6297
6298static void vmsvgaColor2GLFloatArray(uint32_t color, GLfloat *pRed, GLfloat *pGreen, GLfloat *pBlue, GLfloat *pAlpha)
6299{
6300 /* Convert byte color components to float (0-1.0) */
6301 *pAlpha = (GLfloat)(color >> 24) / 255.0;
6302 *pRed = (GLfloat)((color >> 16) & 0xff) / 255.0;
6303 *pGreen = (GLfloat)((color >> 8) & 0xff) / 255.0;
6304 *pBlue = (GLfloat)(color & 0xff) / 255.0;
6305}
6306
6307static DECLCALLBACK(int) vmsvga3dBackCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil,
6308 uint32_t cRects, SVGA3dRect *pRect)
6309{
6310 GLbitfield mask = 0;
6311 GLbitfield restoreMask = 0;
6312 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6313 AssertReturn(pState, VERR_NO_MEMORY);
6314 GLboolean fDepthWriteEnabled = GL_FALSE;
6315 GLboolean afColorWriteEnabled[4] = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE };
6316
6317 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));
6318
6319 PVMSVGA3DCONTEXT pContext;
6320 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
6321 AssertRCReturn(rc, rc);
6322
6323 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6324
6325 if (clearFlag & SVGA3D_CLEAR_COLOR)
6326 {
6327 GLfloat red, green, blue, alpha;
6328 vmsvgaColor2GLFloatArray(color, &red, &green, &blue, &alpha);
6329
6330 /* Set the color clear value. */
6331 glClearColor(red, green, blue, alpha);
6332 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6333
6334 mask |= GL_COLOR_BUFFER_BIT;
6335
6336 /* glClear will not clear the color buffer if writing is disabled. */
6337 glGetBooleanv(GL_COLOR_WRITEMASK, afColorWriteEnabled);
6338 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6339 if ( afColorWriteEnabled[0] == GL_FALSE
6340 || afColorWriteEnabled[1] == GL_FALSE
6341 || afColorWriteEnabled[2] == GL_FALSE
6342 || afColorWriteEnabled[3] == GL_FALSE)
6343 {
6344 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
6345 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6346
6347 restoreMask |= GL_COLOR_BUFFER_BIT;
6348 }
6349
6350 }
6351
6352 if (clearFlag & SVGA3D_CLEAR_STENCIL)
6353 {
6354 /** @todo possibly the same problem as with glDepthMask */
6355 glClearStencil(stencil);
6356 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6357
6358 mask |= GL_STENCIL_BUFFER_BIT;
6359 }
6360
6361 if (clearFlag & SVGA3D_CLEAR_DEPTH)
6362 {
6363 glClearDepth((GLdouble)depth);
6364 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6365
6366 mask |= GL_DEPTH_BUFFER_BIT;
6367
6368 /* glClear will not clear the depth buffer if writing is disabled. */
6369 glGetBooleanv(GL_DEPTH_WRITEMASK, &fDepthWriteEnabled);
6370 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6371 if (fDepthWriteEnabled == GL_FALSE)
6372 {
6373 glDepthMask(GL_TRUE);
6374 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6375
6376 restoreMask |= GL_DEPTH_BUFFER_BIT;
6377 }
6378 }
6379
6380 /* Save the current scissor test bit and scissor box. */
6381 glPushAttrib(GL_SCISSOR_BIT);
6382 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6383
6384 if (cRects)
6385 {
6386 glEnable(GL_SCISSOR_TEST);
6387 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6388
6389 for (uint32_t i = 0; i < cRects; ++i)
6390 {
6391 LogFunc(("rect [%d] %d,%d %dx%d)\n", i, pRect[i].x, pRect[i].y, pRect[i].w, pRect[i].h));
6392 glScissor(pRect[i].x, pRect[i].y, pRect[i].w, pRect[i].h);
6393 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6394
6395 glClear(mask);
6396 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6397 }
6398 }
6399 else
6400 {
6401 glDisable(GL_SCISSOR_TEST);
6402 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6403
6404 glClear(mask);
6405 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6406 }
6407
6408 /* Restore the old scissor test bit and box */
6409 glPopAttrib();
6410 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6411
6412 /* Restore the write states. */
6413 if (restoreMask & GL_COLOR_BUFFER_BIT)
6414 {
6415 glColorMask(afColorWriteEnabled[0],
6416 afColorWriteEnabled[1],
6417 afColorWriteEnabled[2],
6418 afColorWriteEnabled[3]);
6419 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6420 }
6421
6422 if (restoreMask & GL_DEPTH_BUFFER_BIT)
6423 {
6424 glDepthMask(fDepthWriteEnabled);
6425 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6426 }
6427
6428 return VINF_SUCCESS;
6429}
6430
6431/* Convert VMWare vertex declaration to its OpenGL equivalent. */
6432int vmsvga3dVertexDecl2OGL(SVGA3dVertexArrayIdentity &identity, GLint &size, GLenum &type, GLboolean &normalized, uint32_t &cbAttrib)
6433{
6434 normalized = GL_FALSE;
6435 switch (identity.type)
6436 {
6437 case SVGA3D_DECLTYPE_FLOAT1:
6438 size = 1;
6439 type = GL_FLOAT;
6440 cbAttrib = sizeof(float);
6441 break;
6442 case SVGA3D_DECLTYPE_FLOAT2:
6443 size = 2;
6444 type = GL_FLOAT;
6445 cbAttrib = 2 * sizeof(float);
6446 break;
6447 case SVGA3D_DECLTYPE_FLOAT3:
6448 size = 3;
6449 type = GL_FLOAT;
6450 cbAttrib = 3 * sizeof(float);
6451 break;
6452 case SVGA3D_DECLTYPE_FLOAT4:
6453 size = 4;
6454 type = GL_FLOAT;
6455 cbAttrib = 4 * sizeof(float);
6456 break;
6457
6458 case SVGA3D_DECLTYPE_D3DCOLOR:
6459 size = GL_BGRA; /* @note requires GL_ARB_vertex_array_bgra */
6460 type = GL_UNSIGNED_BYTE;
6461 normalized = GL_TRUE; /* glVertexAttribPointer fails otherwise */
6462 cbAttrib = sizeof(uint32_t);
6463 break;
6464
6465 case SVGA3D_DECLTYPE_UBYTE4N:
6466 normalized = GL_TRUE;
6467 RT_FALL_THRU();
6468 case SVGA3D_DECLTYPE_UBYTE4:
6469 size = 4;
6470 type = GL_UNSIGNED_BYTE;
6471 cbAttrib = sizeof(uint32_t);
6472 break;
6473
6474 case SVGA3D_DECLTYPE_SHORT2N:
6475 normalized = GL_TRUE;
6476 RT_FALL_THRU();
6477 case SVGA3D_DECLTYPE_SHORT2:
6478 size = 2;
6479 type = GL_SHORT;
6480 cbAttrib = 2 * sizeof(uint16_t);
6481 break;
6482
6483 case SVGA3D_DECLTYPE_SHORT4N:
6484 normalized = GL_TRUE;
6485 RT_FALL_THRU();
6486 case SVGA3D_DECLTYPE_SHORT4:
6487 size = 4;
6488 type = GL_SHORT;
6489 cbAttrib = 4 * sizeof(uint16_t);
6490 break;
6491
6492 case SVGA3D_DECLTYPE_USHORT4N:
6493 normalized = GL_TRUE;
6494 size = 4;
6495 type = GL_UNSIGNED_SHORT;
6496 cbAttrib = 4 * sizeof(uint16_t);
6497 break;
6498
6499 case SVGA3D_DECLTYPE_USHORT2N:
6500 normalized = GL_TRUE;
6501 size = 2;
6502 type = GL_UNSIGNED_SHORT;
6503 cbAttrib = 2 * sizeof(uint16_t);
6504 break;
6505
6506 case SVGA3D_DECLTYPE_UDEC3:
6507 size = 3;
6508 type = GL_UNSIGNED_INT_2_10_10_10_REV; /** @todo correct? */
6509 cbAttrib = sizeof(uint32_t);
6510 break;
6511
6512 case SVGA3D_DECLTYPE_DEC3N:
6513 normalized = true;
6514 size = 3;
6515 type = GL_INT_2_10_10_10_REV; /** @todo correct? */
6516 cbAttrib = sizeof(uint32_t);
6517 break;
6518
6519 case SVGA3D_DECLTYPE_FLOAT16_2:
6520 size = 2;
6521 type = GL_HALF_FLOAT;
6522 cbAttrib = 2 * sizeof(uint16_t);
6523 break;
6524 case SVGA3D_DECLTYPE_FLOAT16_4:
6525 size = 4;
6526 type = GL_HALF_FLOAT;
6527 cbAttrib = 4 * sizeof(uint16_t);
6528 break;
6529 default:
6530 AssertFailedReturn(VERR_INVALID_PARAMETER);
6531 }
6532
6533 //pVertexElement->Method = identity.method;
6534 //pVertexElement->Usage = identity.usage;
6535
6536 return VINF_SUCCESS;
6537}
6538
6539static float vmsvga3dFloat16To32(uint16_t f16)
6540{
6541 /* From Wiki */
6542#ifndef INFINITY
6543 static uint32_t const sBitsINFINITY = UINT32_C(0x7f800000);
6544 #define INFINITY (*(float const *)&sBitsINFINITY)
6545#endif
6546#ifndef NAN
6547 static uint32_t const sBitsNAN = UINT32_C(0x7fc00000);
6548 #define NAN (*(float const *)&sBitsNAN)
6549#endif
6550
6551 uint16_t const s = (f16 >> UINT16_C(15)) & UINT16_C(0x1);
6552 uint16_t const e = (f16 >> UINT16_C(10)) & UINT16_C(0x1f);
6553 uint16_t const m = (f16 ) & UINT16_C(0x3ff);
6554
6555 float result = s ? 1.0f : -1.0f;
6556 if (e == 0)
6557 {
6558 if (m == 0)
6559 result *= 0.0f; /* zero, -0 */
6560 else
6561 result *= (float)m / 1024.0f / 16384.0f; /* subnormal numbers: sign * 2^-14 * 0.m */
6562 }
6563 else if (e == 0x1f)
6564 {
6565 if (m == 0)
6566 result *= INFINITY; /* +-infinity */
6567 else
6568 result = NAN; /* NAN */
6569 }
6570 else
6571 {
6572 result *= powf(2.0f, (float)e - 15.0f) * (1.0f + (float)m / 1024.0f); /* sign * 2^(e-15) * 1.m */
6573 }
6574
6575 return result;
6576}
6577
6578/* Set a vertex attribute according to VMSVGA vertex declaration. */
6579static int vmsvga3dSetVertexAttrib(PVMSVGA3DSTATE pState, GLuint index, SVGA3dVertexArrayIdentity const *pIdentity, GLvoid const *pv)
6580{
6581 switch (pIdentity->type)
6582 {
6583 case SVGA3D_DECLTYPE_FLOAT1:
6584 {
6585 /* "One-component float expanded to (float, 0, 0, 1)." */
6586 GLfloat const *p = (GLfloat *)pv;
6587 GLfloat const v[4] = { p[0], 0.0f, 0.0f, 1.0f };
6588 pState->ext.glVertexAttrib4fv(index, v);
6589 break;
6590 }
6591 case SVGA3D_DECLTYPE_FLOAT2:
6592 {
6593 /* "Two-component float expanded to (float, float, 0, 1)." */
6594 GLfloat const *p = (GLfloat *)pv;
6595 GLfloat const v[4] = { p[0], p[1], 0.0f, 1.0f };
6596 pState->ext.glVertexAttrib4fv(index, v);
6597 break;
6598 }
6599 case SVGA3D_DECLTYPE_FLOAT3:
6600 {
6601 /* "Three-component float expanded to (float, float, float, 1)." */
6602 GLfloat const *p = (GLfloat *)pv;
6603 GLfloat const v[4] = { p[0], p[1], p[2], 1.0f };
6604 pState->ext.glVertexAttrib4fv(index, v);
6605 break;
6606 }
6607 case SVGA3D_DECLTYPE_FLOAT4:
6608 pState->ext.glVertexAttrib4fv(index, (GLfloat const *)pv);
6609 break;
6610 case SVGA3D_DECLTYPE_D3DCOLOR:
6611 /** @todo Need to swap bytes? */
6612 pState->ext.glVertexAttrib4Nubv(index, (GLubyte const *)pv);
6613 break;
6614 case SVGA3D_DECLTYPE_UBYTE4:
6615 pState->ext.glVertexAttrib4ubv(index, (GLubyte const *)pv);
6616 break;
6617 case SVGA3D_DECLTYPE_SHORT2:
6618 {
6619 /* "Two-component, signed short expanded to (value, value, 0, 1)." */
6620 GLshort const *p = (GLshort const *)pv;
6621 GLshort const v[4] = { p[0], p[1], 0, 1 };
6622 pState->ext.glVertexAttrib4sv(index, v);
6623 break;
6624 }
6625 case SVGA3D_DECLTYPE_SHORT4:
6626 pState->ext.glVertexAttrib4sv(index, (GLshort const *)pv);
6627 break;
6628 case SVGA3D_DECLTYPE_UBYTE4N:
6629 pState->ext.glVertexAttrib4Nubv(index, (GLubyte const *)pv);
6630 break;
6631 case SVGA3D_DECLTYPE_SHORT2N:
6632 {
6633 /* "Normalized, two-component, signed short, expanded to (first short/32767.0, second short/32767.0, 0, 1)." */
6634 GLshort const *p = (GLshort const *)pv;
6635 GLshort const v[4] = { p[0], p[1], 0, 1 };
6636 pState->ext.glVertexAttrib4Nsv(index, v);
6637 break;
6638 }
6639 case SVGA3D_DECLTYPE_SHORT4N:
6640 pState->ext.glVertexAttrib4Nsv(index, (GLshort const *)pv);
6641 break;
6642 case SVGA3D_DECLTYPE_USHORT2N:
6643 {
6644 GLushort const *p = (GLushort const *)pv;
6645 GLushort const v[4] = { p[0], p[1], 0, 1 };
6646 pState->ext.glVertexAttrib4Nusv(index, v);
6647 break;
6648 }
6649 case SVGA3D_DECLTYPE_USHORT4N:
6650 pState->ext.glVertexAttrib4Nusv(index, (GLushort const *)pv);
6651 break;
6652 case SVGA3D_DECLTYPE_UDEC3:
6653 {
6654 /** @todo Test */
6655 /* "Three-component, unsigned, 10 10 10 format expanded to (value, value, value, 1)." */
6656 uint32_t const u32 = *(uint32_t *)pv;
6657 GLfloat const v[4] = { (float)(u32 & 0x3ff), (float)((u32 >> 10) & 0x3ff), (float)((u32 >> 20) & 0x3ff), 1.0f };
6658 pState->ext.glVertexAttrib4fv(index, v);
6659 break;
6660 }
6661 case SVGA3D_DECLTYPE_DEC3N:
6662 {
6663 /** @todo Test */
6664 /* "Three-component, signed, 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)." */
6665 uint32_t const u32 = *(uint32_t *)pv;
6666 GLfloat const v[4] = { (u32 & 0x3ff) / 511.0f, ((u32 >> 10) & 0x3ff) / 511.0f, ((u32 >> 20) & 0x3ff) / 511.0f, 1.0f };
6667 pState->ext.glVertexAttrib4fv(index, v);
6668 break;
6669 }
6670 case SVGA3D_DECLTYPE_FLOAT16_2:
6671 {
6672 /** @todo Test */
6673 /* "Two-component, 16-bit, floating point expanded to (value, value, 0, 1)." */
6674 uint16_t const *p = (uint16_t *)pv;
6675 GLfloat const v[4] = { vmsvga3dFloat16To32(p[0]), vmsvga3dFloat16To32(p[1]), 0.0f, 1.0f };
6676 pState->ext.glVertexAttrib4fv(index, v);
6677 break;
6678 }
6679 case SVGA3D_DECLTYPE_FLOAT16_4:
6680 {
6681 /** @todo Test */
6682 uint16_t const *p = (uint16_t *)pv;
6683 GLfloat const v[4] = { vmsvga3dFloat16To32(p[0]), vmsvga3dFloat16To32(p[1]),
6684 vmsvga3dFloat16To32(p[2]), vmsvga3dFloat16To32(p[3]) };
6685 pState->ext.glVertexAttrib4fv(index, v);
6686 break;
6687 }
6688 default:
6689 AssertFailedReturn(VERR_INVALID_PARAMETER);
6690 }
6691
6692 return VINF_SUCCESS;
6693}
6694
6695/* Convert VMWare primitive type to its OpenGL equivalent. */
6696/* Calculate the vertex count based on the primitive type and nr of primitives. */
6697int vmsvga3dPrimitiveType2OGL(SVGA3dPrimitiveType PrimitiveType, GLenum *pMode, uint32_t cPrimitiveCount, uint32_t *pcVertices)
6698{
6699 switch (PrimitiveType)
6700 {
6701 case SVGA3D_PRIMITIVE_TRIANGLELIST:
6702 *pMode = GL_TRIANGLES;
6703 *pcVertices = cPrimitiveCount * 3;
6704 break;
6705 case SVGA3D_PRIMITIVE_POINTLIST:
6706 *pMode = GL_POINTS;
6707 *pcVertices = cPrimitiveCount;
6708 break;
6709 case SVGA3D_PRIMITIVE_LINELIST:
6710 *pMode = GL_LINES;
6711 *pcVertices = cPrimitiveCount * 2;
6712 break;
6713 case SVGA3D_PRIMITIVE_LINESTRIP:
6714 *pMode = GL_LINE_STRIP;
6715 *pcVertices = cPrimitiveCount + 1;
6716 break;
6717 case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
6718 *pMode = GL_TRIANGLE_STRIP;
6719 *pcVertices = cPrimitiveCount + 2;
6720 break;
6721 case SVGA3D_PRIMITIVE_TRIANGLEFAN:
6722 *pMode = GL_TRIANGLE_FAN;
6723 *pcVertices = cPrimitiveCount + 2;
6724 break;
6725 default:
6726 return VERR_INVALID_PARAMETER;
6727 }
6728 return VINF_SUCCESS;
6729}
6730
6731static int vmsvga3dResetTransformMatrices(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
6732{
6733 int rc;
6734
6735 /* Reset the view matrix (also takes the world matrix into account). */
6736 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].fValid == true)
6737 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_VIEW,
6738 pContext->state.aTransformState[SVGA3D_TRANSFORM_VIEW].matrix);
6739 else
6740 {
6741 float matrix[16];
6742
6743 /* identity matrix if no matrix set. */
6744 memset(matrix, 0, sizeof(matrix));
6745 matrix[0] = 1.0;
6746 matrix[5] = 1.0;
6747 matrix[10] = 1.0;
6748 matrix[15] = 1.0;
6749 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_VIEW, matrix);
6750 }
6751
6752 /* Reset the projection matrix. */
6753 if (pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].fValid == true)
6754 {
6755 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_PROJECTION, pContext->state.aTransformState[SVGA3D_TRANSFORM_PROJECTION].matrix);
6756 }
6757 else
6758 {
6759 float matrix[16];
6760
6761 /* identity matrix if no matrix set. */
6762 memset(matrix, 0, sizeof(matrix));
6763 matrix[0] = 1.0;
6764 matrix[5] = 1.0;
6765 matrix[10] = 1.0;
6766 matrix[15] = 1.0;
6767 rc = vmsvga3dBackSetTransform(pThisCC, pContext->id, SVGA3D_TRANSFORM_PROJECTION, matrix);
6768 }
6769 AssertRC(rc);
6770 return rc;
6771}
6772
6773static int vmsvga3dDrawPrimitivesProcessVertexDecls(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext,
6774 uint32_t iVertexDeclBase, uint32_t numVertexDecls,
6775 SVGA3dVertexDecl *pVertexDecl,
6776 SVGA3dVertexDivisor const *paVertexDivisors)
6777{
6778 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6779 unsigned const sidVertex = pVertexDecl[0].array.surfaceId;
6780
6781 PVMSVGA3DSURFACE pVertexSurface;
6782 int rc = vmsvga3dSurfaceFromSid(pState, sidVertex, &pVertexSurface);
6783 AssertRCReturn(rc, rc);
6784
6785 Log(("vmsvga3dDrawPrimitives: vertex surface sid=%u\n", sidVertex));
6786
6787 /* Create and/or bind the vertex buffer. */
6788 if (pVertexSurface->oglId.buffer == OPENGL_INVALID_ID)
6789 {
6790 Log(("vmsvga3dDrawPrimitives: create vertex buffer fDirty=%d size=%x bytes\n", pVertexSurface->fDirty, pVertexSurface->paMipmapLevels[0].cbSurface));
6791 PVMSVGA3DCONTEXT pSavedCtx = pContext;
6792 pContext = &pState->SharedCtx;
6793 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6794
6795 pState->ext.glGenBuffers(1, &pVertexSurface->oglId.buffer);
6796 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6797 pVertexSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_BUFFER;
6798
6799 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pVertexSurface->oglId.buffer);
6800 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6801
6802 Assert(pVertexSurface->fDirty);
6803 /** @todo rethink usage dynamic/static */
6804 pState->ext.glBufferData(GL_ARRAY_BUFFER, pVertexSurface->paMipmapLevels[0].cbSurface, pVertexSurface->paMipmapLevels[0].pSurfaceData, GL_DYNAMIC_DRAW);
6805 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6806
6807 pVertexSurface->paMipmapLevels[0].fDirty = false;
6808 pVertexSurface->fDirty = false;
6809
6810 pVertexSurface->surfaceFlags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
6811
6812 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, OPENGL_INVALID_ID);
6813 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6814
6815 pContext = pSavedCtx;
6816 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
6817 }
6818
6819 Assert(pVertexSurface->fDirty == false);
6820 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pVertexSurface->oglId.buffer);
6821 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6822
6823 /* Setup the vertex declarations. */
6824 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
6825 {
6826 GLint size;
6827 GLenum type;
6828 GLboolean normalized;
6829 uint32_t cbAttrib;
6830 GLuint index = iVertexDeclBase + iVertex;
6831
6832 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));
6833
6834 rc = vmsvga3dVertexDecl2OGL(pVertexDecl[iVertex].identity, size, type, normalized, cbAttrib);
6835 AssertRCReturn(rc, rc);
6836
6837 ASSERT_GUEST_RETURN( pVertexSurface->paMipmapLevels[0].cbSurface >= pVertexDecl[iVertex].array.offset
6838 && pVertexSurface->paMipmapLevels[0].cbSurface - pVertexDecl[iVertex].array.offset >= cbAttrib,
6839 VERR_INVALID_PARAMETER);
6840 RT_UNTRUSTED_VALIDATED_FENCE();
6841
6842 if (pContext->state.shidVertex != SVGA_ID_INVALID)
6843 {
6844 /* Use numbered vertex arrays (or attributes) when shaders are active. */
6845 if (pVertexDecl[iVertex].array.stride)
6846 {
6847 pState->ext.glEnableVertexAttribArray(index);
6848 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6849 pState->ext.glVertexAttribPointer(index, size, type, normalized, pVertexDecl[iVertex].array.stride,
6850 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6851 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6852
6853 GLuint divisor = paVertexDivisors && paVertexDivisors[index].instanceData ? 1 : 0;
6854 pState->ext.glVertexAttribDivisor(index, divisor);
6855 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6856
6857 /** @todo case SVGA3D_DECLUSAGE_COLOR: color component order not identical!! test GL_BGRA!! */
6858 }
6859 else
6860 {
6861 /*
6862 * D3D and OpenGL have a different meaning of value zero for the vertex array stride:
6863 * - D3D (VMSVGA): "use a zero stride to tell the runtime not to increment the vertex buffer offset."
6864 * - OpenGL: "If stride is 0, the generic vertex attributes are understood to be tightly packed in the array."
6865 * VMSVGA uses the D3D semantics.
6866 *
6867 * Use glVertexAttrib in order to tell OpenGL to reuse the zero stride attributes for each vertex.
6868 */
6869 pState->ext.glDisableVertexAttribArray(index);
6870 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6871
6872 const GLvoid *v = (uint8_t *)pVertexSurface->paMipmapLevels[0].pSurfaceData + pVertexDecl[iVertex].array.offset;
6873 vmsvga3dSetVertexAttrib(pState, index, &pVertexDecl[iVertex].identity, v);
6874 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
6875 }
6876 }
6877 else
6878 {
6879 if (pVertexDecl[iVertex].array.stride == 0)
6880 {
6881 /* Zero stride means that the attribute pointer must not be increased.
6882 * See comment about stride in vmsvga3dDrawPrimitives.
6883 */
6884 LogRelMax(8, ("VMSVGA: Warning: zero stride array in fixed function pipeline\n"));
6885 AssertFailed();
6886 }
6887
6888 /* Use the predefined selection of vertex streams for the fixed pipeline. */
6889 switch (pVertexDecl[iVertex].identity.usage)
6890 {
6891 case SVGA3D_DECLUSAGE_POSITIONT:
6892 case SVGA3D_DECLUSAGE_POSITION:
6893 {
6894 glEnableClientState(GL_VERTEX_ARRAY);
6895 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6896 glVertexPointer(size, type, pVertexDecl[iVertex].array.stride,
6897 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6898 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6899 break;
6900 }
6901 case SVGA3D_DECLUSAGE_BLENDWEIGHT:
6902 AssertFailed();
6903 break;
6904 case SVGA3D_DECLUSAGE_BLENDINDICES:
6905 AssertFailed();
6906 break;
6907 case SVGA3D_DECLUSAGE_NORMAL:
6908 glEnableClientState(GL_NORMAL_ARRAY);
6909 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6910 glNormalPointer(type, pVertexDecl[iVertex].array.stride,
6911 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6912 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6913 break;
6914 case SVGA3D_DECLUSAGE_PSIZE:
6915 AssertFailed();
6916 break;
6917 case SVGA3D_DECLUSAGE_TEXCOORD:
6918 /* Specify the affected texture unit. */
6919#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x103
6920 glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
6921#else
6922 pState->ext.glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
6923#endif
6924 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
6925 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6926 glTexCoordPointer(size, type, pVertexDecl[iVertex].array.stride,
6927 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6928 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6929 break;
6930 case SVGA3D_DECLUSAGE_TANGENT:
6931 AssertFailed();
6932 break;
6933 case SVGA3D_DECLUSAGE_BINORMAL:
6934 AssertFailed();
6935 break;
6936 case SVGA3D_DECLUSAGE_TESSFACTOR:
6937 AssertFailed();
6938 break;
6939 case SVGA3D_DECLUSAGE_COLOR: /** @todo color component order not identical!! test GL_BGRA!! */
6940 glEnableClientState(GL_COLOR_ARRAY);
6941 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6942 glColorPointer(size, type, pVertexDecl[iVertex].array.stride,
6943 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6944 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6945 break;
6946 case SVGA3D_DECLUSAGE_FOG:
6947 glEnableClientState(GL_FOG_COORD_ARRAY);
6948 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6949 pState->ext.glFogCoordPointer(type, pVertexDecl[iVertex].array.stride,
6950 (const GLvoid *)(uintptr_t)pVertexDecl[iVertex].array.offset);
6951 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6952 break;
6953 case SVGA3D_DECLUSAGE_DEPTH:
6954 AssertFailed();
6955 break;
6956 case SVGA3D_DECLUSAGE_SAMPLE:
6957 AssertFailed();
6958 break;
6959 case SVGA3D_DECLUSAGE_MAX: AssertFailed(); break; /* shut up gcc */
6960 }
6961 }
6962
6963#ifdef LOG_ENABLED
6964 if (pVertexDecl[iVertex].array.stride == 0)
6965 Log(("vmsvga3dDrawPrimitives: stride == 0! Can be valid\n"));
6966#endif
6967 }
6968
6969 return VINF_SUCCESS;
6970}
6971
6972static int vmsvga3dDrawPrimitivesCleanupVertexDecls(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t iVertexDeclBase,
6973 uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl)
6974{
6975 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
6976
6977 /* Clean up the vertex declarations. */
6978 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
6979 {
6980 if (pVertexDecl[iVertex].identity.usage == SVGA3D_DECLUSAGE_POSITIONT)
6981 {
6982 /* Reset the transformation matrices in case of a switch back from pretransformed mode. */
6983 Log(("vmsvga3dDrawPrimitivesCleanupVertexDecls: reset world and projection matrices after transformation reset (pre-transformed -> transformed)\n"));
6984 vmsvga3dResetTransformMatrices(pThisCC, pContext);
6985 }
6986
6987 if (pContext->state.shidVertex != SVGA_ID_INVALID)
6988 {
6989 /* Use numbered vertex arrays when shaders are active. */
6990 pState->ext.glVertexAttribDivisor(iVertexDeclBase + iVertex, 0);
6991 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6992 pState->ext.glDisableVertexAttribArray(iVertexDeclBase + iVertex);
6993 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
6994 }
6995 else
6996 {
6997 /* Use the predefined selection of vertex streams for the fixed pipeline. */
6998 switch (pVertexDecl[iVertex].identity.usage)
6999 {
7000 case SVGA3D_DECLUSAGE_POSITION:
7001 case SVGA3D_DECLUSAGE_POSITIONT:
7002 glDisableClientState(GL_VERTEX_ARRAY);
7003 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7004 break;
7005 case SVGA3D_DECLUSAGE_BLENDWEIGHT:
7006 break;
7007 case SVGA3D_DECLUSAGE_BLENDINDICES:
7008 break;
7009 case SVGA3D_DECLUSAGE_NORMAL:
7010 glDisableClientState(GL_NORMAL_ARRAY);
7011 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7012 break;
7013 case SVGA3D_DECLUSAGE_PSIZE:
7014 break;
7015 case SVGA3D_DECLUSAGE_TEXCOORD:
7016 /* Specify the affected texture unit. */
7017#if VBOX_VMSVGA3D_GL_HACK_LEVEL >= 0x103
7018 glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
7019#else
7020 pState->ext.glClientActiveTexture(GL_TEXTURE0 + pVertexDecl[iVertex].identity.usageIndex);
7021#endif
7022 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
7023 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7024 break;
7025 case SVGA3D_DECLUSAGE_TANGENT:
7026 break;
7027 case SVGA3D_DECLUSAGE_BINORMAL:
7028 break;
7029 case SVGA3D_DECLUSAGE_TESSFACTOR:
7030 break;
7031 case SVGA3D_DECLUSAGE_COLOR: /** @todo color component order not identical!! */
7032 glDisableClientState(GL_COLOR_ARRAY);
7033 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7034 break;
7035 case SVGA3D_DECLUSAGE_FOG:
7036 glDisableClientState(GL_FOG_COORD_ARRAY);
7037 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7038 break;
7039 case SVGA3D_DECLUSAGE_DEPTH:
7040 break;
7041 case SVGA3D_DECLUSAGE_SAMPLE:
7042 break;
7043 case SVGA3D_DECLUSAGE_MAX: AssertFailed(); break; /* shut up gcc */
7044 }
7045 }
7046 }
7047 /* Unbind the vertex buffer after usage. */
7048 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
7049 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7050 return VINF_SUCCESS;
7051}
7052
7053static DECLCALLBACK(int) vmsvga3dBackDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl,
7054 uint32_t numRanges, SVGA3dPrimitiveRange *pRange, uint32_t cVertexDivisor,
7055 SVGA3dVertexDivisor *pVertexDivisor)
7056{
7057 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7058 AssertReturn(pState, VERR_INTERNAL_ERROR);
7059 uint32_t iCurrentVertex;
7060
7061 Log(("vmsvga3dDrawPrimitives cid=%u numVertexDecls=%d numRanges=%d, cVertexDivisor=%d\n", cid, numVertexDecls, numRanges, cVertexDivisor));
7062
7063 /* Caller already check these, but it cannot hurt to check again... */
7064 AssertReturn(numVertexDecls && numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, VERR_INVALID_PARAMETER);
7065 AssertReturn(numRanges && numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, VERR_INVALID_PARAMETER);
7066 AssertReturn(!cVertexDivisor || cVertexDivisor == numVertexDecls, VERR_INVALID_PARAMETER);
7067
7068 if (!cVertexDivisor)
7069 pVertexDivisor = NULL; /* Be sure. */
7070
7071 PVMSVGA3DCONTEXT pContext;
7072 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7073 AssertRCReturn(rc, rc);
7074
7075 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7076
7077 /* Check for pretransformed vertex declarations. */
7078 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
7079 {
7080 switch (pVertexDecl[iVertex].identity.usage)
7081 {
7082 case SVGA3D_DECLUSAGE_POSITIONT:
7083 Log(("ShaderSetPositionTransformed: (%d,%d)\n", pContext->state.RectViewPort.w, pContext->state.RectViewPort.h));
7084 RT_FALL_THRU();
7085 case SVGA3D_DECLUSAGE_POSITION:
7086 ShaderSetPositionTransformed(pContext->pShaderContext, pContext->state.RectViewPort.w,
7087 pContext->state.RectViewPort.h,
7088 pVertexDecl[iVertex].identity.usage == SVGA3D_DECLUSAGE_POSITIONT);
7089 break;
7090 default: /* Shut up MSC. */ break;
7091 }
7092 }
7093
7094 /* Flush any shader changes; after (!) checking the vertex declarations to deal with pre-transformed vertices. */
7095 if (pContext->pShaderContext)
7096 {
7097 uint32_t rtHeight = 0;
7098
7099 if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA_ID_INVALID)
7100 {
7101 PVMSVGA3DSURFACE pRenderTarget;
7102 rc = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pRenderTarget);
7103 AssertRCReturn(rc, rc);
7104
7105 rtHeight = pRenderTarget->paMipmapLevels[0].mipmapSize.height;
7106 }
7107
7108 ShaderUpdateState(pContext->pShaderContext, rtHeight);
7109 }
7110
7111 /* Try to figure out if instancing is used.
7112 * Support simple instancing case with one set of indexed data and one set per-instance data.
7113 */
7114 uint32_t cInstances = 0;
7115 for (uint32_t iVertexDivisor = 0; iVertexDivisor < cVertexDivisor; ++iVertexDivisor)
7116 {
7117 if (pVertexDivisor[iVertexDivisor].indexedData)
7118 {
7119 if (cInstances == 0)
7120 cInstances = pVertexDivisor[iVertexDivisor].count;
7121 else
7122 Assert(cInstances == pVertexDivisor[iVertexDivisor].count);
7123 }
7124 else if (pVertexDivisor[iVertexDivisor].instanceData)
7125 {
7126 Assert(pVertexDivisor[iVertexDivisor].count == 1);
7127 }
7128 }
7129
7130 /* Process all vertex declarations. Each vertex buffer is represented by one stream. */
7131 iCurrentVertex = 0;
7132 while (iCurrentVertex < numVertexDecls)
7133 {
7134 uint32_t sidVertex = SVGA_ID_INVALID;
7135 uint32_t iVertex;
7136
7137 for (iVertex = iCurrentVertex; iVertex < numVertexDecls; iVertex++)
7138 {
7139 if ( sidVertex != SVGA_ID_INVALID
7140 && pVertexDecl[iVertex].array.surfaceId != sidVertex
7141 )
7142 break;
7143 sidVertex = pVertexDecl[iVertex].array.surfaceId;
7144 }
7145
7146 rc = vmsvga3dDrawPrimitivesProcessVertexDecls(pThisCC, pContext, iCurrentVertex, iVertex - iCurrentVertex,
7147 &pVertexDecl[iCurrentVertex], pVertexDivisor);
7148 AssertRCReturn(rc, rc);
7149
7150 iCurrentVertex = iVertex;
7151 }
7152
7153 /* Now draw the primitives. */
7154 for (unsigned iPrimitive = 0; iPrimitive < numRanges; iPrimitive++)
7155 {
7156 GLenum modeDraw;
7157 unsigned const sidIndex = pRange[iPrimitive].indexArray.surfaceId;
7158 PVMSVGA3DSURFACE pIndexSurface = NULL;
7159 unsigned cVertices;
7160
7161 Log(("Primitive %d: type %s\n", iPrimitive, vmsvga3dPrimitiveType2String(pRange[iPrimitive].primType)));
7162 rc = vmsvga3dPrimitiveType2OGL(pRange[iPrimitive].primType, &modeDraw, pRange[iPrimitive].primitiveCount, &cVertices);
7163 if (RT_FAILURE(rc))
7164 {
7165 AssertRC(rc);
7166 goto internal_error;
7167 }
7168
7169 if (sidIndex != SVGA3D_INVALID_ID)
7170 {
7171 AssertMsg(pRange[iPrimitive].indexWidth == sizeof(uint32_t) || pRange[iPrimitive].indexWidth == sizeof(uint16_t), ("Unsupported primitive width %d\n", pRange[iPrimitive].indexWidth));
7172
7173 rc = vmsvga3dSurfaceFromSid(pState, sidIndex, &pIndexSurface);
7174 if (RT_FAILURE(rc))
7175 {
7176 AssertRC(rc);
7177 goto internal_error;
7178 }
7179
7180 Log(("vmsvga3dDrawPrimitives: index surface sid=%u\n", sidIndex));
7181
7182 if (pIndexSurface->oglId.buffer == OPENGL_INVALID_ID)
7183 {
7184 Log(("vmsvga3dDrawPrimitives: create index buffer fDirty=%d size=%x bytes\n", pIndexSurface->fDirty, pIndexSurface->paMipmapLevels[0].cbSurface));
7185 pContext = &pState->SharedCtx;
7186 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7187
7188 pState->ext.glGenBuffers(1, &pIndexSurface->oglId.buffer);
7189 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7190 pIndexSurface->enmOGLResType = VMSVGA3D_OGLRESTYPE_BUFFER;
7191
7192 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->oglId.buffer);
7193 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7194
7195 Assert(pIndexSurface->fDirty);
7196
7197 /** @todo rethink usage dynamic/static */
7198 pState->ext.glBufferData(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->paMipmapLevels[0].cbSurface, pIndexSurface->paMipmapLevels[0].pSurfaceData, GL_DYNAMIC_DRAW);
7199 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7200
7201 pIndexSurface->paMipmapLevels[0].fDirty = false;
7202 pIndexSurface->fDirty = false;
7203
7204 pIndexSurface->surfaceFlags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
7205
7206 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OPENGL_INVALID_ID);
7207 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7208
7209 pContext = pState->papContexts[cid];
7210 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7211 }
7212 Assert(pIndexSurface->fDirty == false);
7213
7214 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pIndexSurface->oglId.buffer);
7215 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7216 }
7217
7218 if (!pIndexSurface)
7219 {
7220 /* Render without an index buffer */
7221 Log(("DrawPrimitive %d cPrimitives=%d cVertices=%d index index bias=%d cInstances=%d\n", modeDraw, pRange[iPrimitive].primitiveCount, cVertices, pRange[iPrimitive].indexBias, cInstances));
7222 if (cInstances == 0)
7223 {
7224 glDrawArrays(modeDraw, pRange[iPrimitive].indexBias, cVertices);
7225 }
7226 else
7227 {
7228 pState->ext.glDrawArraysInstanced(modeDraw, pRange[iPrimitive].indexBias, cVertices, cInstances);
7229 }
7230 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7231 }
7232 else
7233 {
7234 Assert(pRange[iPrimitive].indexWidth == pRange[iPrimitive].indexArray.stride);
7235
7236 GLenum indexType;
7237 switch (pRange[iPrimitive].indexWidth)
7238 {
7239 case 1: indexType = GL_UNSIGNED_BYTE; break;
7240 case 2: indexType = GL_UNSIGNED_SHORT; break;
7241 default: AssertMsgFailed(("indexWidth %d\n", pRange[iPrimitive].indexWidth));
7242 RT_FALL_THROUGH();
7243 case 4: indexType = GL_UNSIGNED_INT; break;
7244 }
7245
7246 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));
7247 if (cInstances == 0)
7248 {
7249 /* Render with an index buffer */
7250 if (pRange[iPrimitive].indexBias == 0)
7251 glDrawElements(modeDraw,
7252 cVertices,
7253 indexType,
7254 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset); /* byte offset in indices buffer */
7255 else
7256 pState->ext.glDrawElementsBaseVertex(modeDraw,
7257 cVertices,
7258 indexType,
7259 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */
7260 pRange[iPrimitive].indexBias); /* basevertex */
7261 }
7262 else
7263 {
7264 /* Render with an index buffer */
7265 if (pRange[iPrimitive].indexBias == 0)
7266 pState->ext.glDrawElementsInstanced(modeDraw,
7267 cVertices,
7268 indexType,
7269 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */
7270 cInstances);
7271 else
7272 pState->ext.glDrawElementsInstancedBaseVertex(modeDraw,
7273 cVertices,
7274 indexType,
7275 (GLvoid *)(uintptr_t)pRange[iPrimitive].indexArray.offset, /* byte offset in indices buffer */
7276 cInstances,
7277 pRange[iPrimitive].indexBias); /* basevertex */
7278 }
7279 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7280
7281 /* Unbind the index buffer after usage. */
7282 pState->ext.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
7283 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7284 }
7285 }
7286
7287internal_error:
7288
7289 /* Deactivate the vertex declarations. */
7290 iCurrentVertex = 0;
7291 while (iCurrentVertex < numVertexDecls)
7292 {
7293 uint32_t sidVertex = SVGA_ID_INVALID;
7294 uint32_t iVertex;
7295
7296 for (iVertex = iCurrentVertex; iVertex < numVertexDecls; iVertex++)
7297 {
7298 if ( sidVertex != SVGA_ID_INVALID
7299 && pVertexDecl[iVertex].array.surfaceId != sidVertex
7300 )
7301 break;
7302 sidVertex = pVertexDecl[iVertex].array.surfaceId;
7303 }
7304
7305 rc = vmsvga3dDrawPrimitivesCleanupVertexDecls(pThisCC, pContext, iCurrentVertex,
7306 iVertex - iCurrentVertex, &pVertexDecl[iCurrentVertex]);
7307 AssertRCReturn(rc, rc);
7308
7309 iCurrentVertex = iVertex;
7310 }
7311
7312#ifdef DEBUG
7313 /* Check whether 'activeTexture' on texture unit 'i' matches what we expect. */
7314 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); ++i)
7315 {
7316 if (pContext->aSidActiveTextures[i] != SVGA3D_INVALID_ID)
7317 {
7318 PVMSVGA3DSURFACE pTexture;
7319 int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[i], &pTexture);
7320 AssertContinue(RT_SUCCESS(rc2));
7321
7322 GLint activeTextureUnit = 0;
7323 glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureUnit);
7324 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7325
7326 pState->ext.glActiveTexture(GL_TEXTURE0 + i);
7327 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7328
7329 GLint activeTexture = 0;
7330 glGetIntegerv(pTexture->bindingGL, &activeTexture);
7331 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7332
7333 pState->ext.glActiveTexture(activeTextureUnit);
7334 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7335
7336 AssertMsg(pTexture->oglId.texture == (GLuint)activeTexture,
7337 ("%d vs %d unit %d (active unit %d) sid=%u\n", pTexture->oglId.texture, activeTexture, i,
7338 activeTextureUnit - GL_TEXTURE0, pContext->aSidActiveTextures[i]));
7339 }
7340 }
7341#endif
7342
7343#if 0
7344 /* Dump render target to a bitmap. */
7345 if (pContext->state.aRenderTargets[SVGA3D_RT_COLOR0] != SVGA3D_INVALID_ID)
7346 {
7347 vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0]);
7348 PVMSVGA3DSURFACE pSurface;
7349 int rc2 = vmsvga3dSurfaceFromSid(pState, pContext->state.aRenderTargets[SVGA3D_RT_COLOR0], &pSurface);
7350 if (RT_SUCCESS(rc2))
7351 vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpgl", "rt", "-post");
7352# if 0
7353 /* Stage 0 texture. */
7354 if (pContext->aSidActiveTextures[0] != SVGA3D_INVALID_ID)
7355 {
7356 vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, pContext->aSidActiveTextures[0]);
7357 rc2 = vmsvga3dSurfaceFromSid(pState, pContext->aSidActiveTextures[0], &pSurface);
7358 if (RT_SUCCESS(rc2))
7359 vmsvga3dInfoSurfaceToBitmap(NULL, pSurface, "bmpgl", "rt", "-post-tx");
7360 }
7361# endif
7362 }
7363#endif
7364
7365 return rc;
7366}
7367
7368
7369static DECLCALLBACK(int) vmsvga3dBackShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData)
7370{
7371 PVMSVGA3DSHADER pShader;
7372 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7373 AssertReturn(pState, VERR_NO_MEMORY);
7374
7375 Log(("vmsvga3dShaderDefine cid=%u shid=%d type=%s cbData=0x%x\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cbData));
7376
7377 PVMSVGA3DCONTEXT pContext;
7378 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7379 AssertRCReturn(rc, rc);
7380
7381 AssertReturn(shid < SVGA3D_MAX_SHADER_IDS, VERR_INVALID_PARAMETER);
7382
7383 rc = vmsvga3dShaderParse(type, cbData, pShaderData);
7384 if (RT_FAILURE(rc))
7385 {
7386 AssertRC(rc);
7387 vmsvga3dShaderLogRel("Failed to parse", type, cbData, pShaderData);
7388 return rc;
7389 }
7390
7391 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7392
7393 if (type == SVGA3D_SHADERTYPE_VS)
7394 {
7395 if (shid >= pContext->cVertexShaders)
7396 {
7397 void *pvNew = RTMemRealloc(pContext->paVertexShader, sizeof(VMSVGA3DSHADER) * (shid + 1));
7398 AssertReturn(pvNew, VERR_NO_MEMORY);
7399 pContext->paVertexShader = (PVMSVGA3DSHADER)pvNew;
7400 memset(&pContext->paVertexShader[pContext->cVertexShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cVertexShaders));
7401 for (uint32_t i = pContext->cVertexShaders; i < shid + 1; i++)
7402 pContext->paVertexShader[i].id = SVGA3D_INVALID_ID;
7403 pContext->cVertexShaders = shid + 1;
7404 }
7405 /* If one already exists with this id, then destroy it now. */
7406 if (pContext->paVertexShader[shid].id != SVGA3D_INVALID_ID)
7407 vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paVertexShader[shid].type);
7408
7409 pShader = &pContext->paVertexShader[shid];
7410 }
7411 else
7412 {
7413 Assert(type == SVGA3D_SHADERTYPE_PS);
7414 if (shid >= pContext->cPixelShaders)
7415 {
7416 void *pvNew = RTMemRealloc(pContext->paPixelShader, sizeof(VMSVGA3DSHADER) * (shid + 1));
7417 AssertReturn(pvNew, VERR_NO_MEMORY);
7418 pContext->paPixelShader = (PVMSVGA3DSHADER)pvNew;
7419 memset(&pContext->paPixelShader[pContext->cPixelShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cPixelShaders));
7420 for (uint32_t i = pContext->cPixelShaders; i < shid + 1; i++)
7421 pContext->paPixelShader[i].id = SVGA3D_INVALID_ID;
7422 pContext->cPixelShaders = shid + 1;
7423 }
7424 /* If one already exists with this id, then destroy it now. */
7425 if (pContext->paPixelShader[shid].id != SVGA3D_INVALID_ID)
7426 vmsvga3dBackShaderDestroy(pThisCC, cid, shid, pContext->paPixelShader[shid].type);
7427
7428 pShader = &pContext->paPixelShader[shid];
7429 }
7430
7431 memset(pShader, 0, sizeof(*pShader));
7432 pShader->id = shid;
7433 pShader->cid = cid;
7434 pShader->type = type;
7435 pShader->cbData = cbData;
7436 pShader->pShaderProgram = RTMemAllocZ(cbData);
7437 AssertReturn(pShader->pShaderProgram, VERR_NO_MEMORY);
7438 memcpy(pShader->pShaderProgram, pShaderData, cbData);
7439
7440#ifdef DUMP_SHADER_DISASSEMBLY
7441 LPD3DXBUFFER pDisassembly;
7442 HRESULT hr = D3DXDisassembleShader((const DWORD *)pShaderData, FALSE, NULL, &pDisassembly);
7443 if (hr == D3D_OK)
7444 {
7445 Log(("Shader disassembly:\n%s\n", pDisassembly->GetBufferPointer()));
7446 pDisassembly->Release();
7447 }
7448#endif
7449
7450 switch (type)
7451 {
7452 case SVGA3D_SHADERTYPE_VS:
7453 rc = ShaderCreateVertexShader(pContext->pShaderContext, (const uint32_t *)pShaderData, cbData, &pShader->u.pVertexShader);
7454 AssertRC(rc);
7455 break;
7456
7457 case SVGA3D_SHADERTYPE_PS:
7458 rc = ShaderCreatePixelShader(pContext->pShaderContext, (const uint32_t *)pShaderData, cbData, &pShader->u.pPixelShader);
7459 AssertRC(rc);
7460 break;
7461
7462 default:
7463 AssertFailedReturn(VERR_INVALID_PARAMETER);
7464 }
7465 if (rc != VINF_SUCCESS)
7466 {
7467 vmsvga3dShaderLogRel("Failed to create", type, cbData, pShaderData);
7468
7469 RTMemFree(pShader->pShaderProgram);
7470 memset(pShader, 0, sizeof(*pShader));
7471 pShader->id = SVGA3D_INVALID_ID;
7472 }
7473
7474 return rc;
7475}
7476
7477static DECLCALLBACK(int) vmsvga3dBackShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type)
7478{
7479 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7480 AssertReturn(pState, VERR_NO_MEMORY);
7481 PVMSVGA3DSHADER pShader = NULL;
7482
7483 Log(("vmsvga3dShaderDestroy cid=%u shid=%d type=%s\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL"));
7484
7485 PVMSVGA3DCONTEXT pContext;
7486 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7487 AssertRCReturn(rc, rc);
7488
7489 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7490
7491 if (type == SVGA3D_SHADERTYPE_VS)
7492 {
7493 if ( shid < pContext->cVertexShaders
7494 && pContext->paVertexShader[shid].id == shid)
7495 {
7496 pShader = &pContext->paVertexShader[shid];
7497 rc = ShaderDestroyVertexShader(pContext->pShaderContext, pShader->u.pVertexShader);
7498 AssertRC(rc);
7499 }
7500 }
7501 else
7502 {
7503 Assert(type == SVGA3D_SHADERTYPE_PS);
7504 if ( shid < pContext->cPixelShaders
7505 && pContext->paPixelShader[shid].id == shid)
7506 {
7507 pShader = &pContext->paPixelShader[shid];
7508 rc = ShaderDestroyPixelShader(pContext->pShaderContext, pShader->u.pPixelShader);
7509 AssertRC(rc);
7510 }
7511 }
7512
7513 if (pShader)
7514 {
7515 if (pShader->pShaderProgram)
7516 RTMemFree(pShader->pShaderProgram);
7517 memset(pShader, 0, sizeof(*pShader));
7518 pShader->id = SVGA3D_INVALID_ID;
7519 }
7520 else
7521 AssertFailedReturn(VERR_INVALID_PARAMETER);
7522
7523 return VINF_SUCCESS;
7524}
7525
7526static DECLCALLBACK(int) vmsvga3dBackShaderSet(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid)
7527{
7528 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7529 AssertReturn(pState, VERR_NO_MEMORY);
7530 int rc;
7531
7532 Log(("vmsvga3dShaderSet cid=%u type=%s shid=%d\n", cid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", shid));
7533
7534 if (!pContext)
7535 {
7536 rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7537 AssertRCReturn(rc, rc);
7538 }
7539
7540 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7541
7542 if (type == SVGA3D_SHADERTYPE_VS)
7543 {
7544 /* Save for vm state save/restore. */
7545 pContext->state.shidVertex = shid;
7546 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VERTEXSHADER;
7547
7548 if ( shid < pContext->cVertexShaders
7549 && pContext->paVertexShader[shid].id == shid)
7550 {
7551 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[shid];
7552 Assert(type == pShader->type);
7553
7554 rc = ShaderSetVertexShader(pContext->pShaderContext, pShader->u.pVertexShader);
7555 AssertRCReturn(rc, rc);
7556 }
7557 else
7558 if (shid == SVGA_ID_INVALID)
7559 {
7560 /* Unselect shader. */
7561 rc = ShaderSetVertexShader(pContext->pShaderContext, NULL);
7562 AssertRCReturn(rc, rc);
7563 }
7564 else
7565 AssertFailedReturn(VERR_INVALID_PARAMETER);
7566 }
7567 else
7568 {
7569 /* Save for vm state save/restore. */
7570 pContext->state.shidPixel = shid;
7571 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_PIXELSHADER;
7572
7573 Assert(type == SVGA3D_SHADERTYPE_PS);
7574 if ( shid < pContext->cPixelShaders
7575 && pContext->paPixelShader[shid].id == shid)
7576 {
7577 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[shid];
7578 Assert(type == pShader->type);
7579
7580 rc = ShaderSetPixelShader(pContext->pShaderContext, pShader->u.pPixelShader);
7581 AssertRCReturn(rc, rc);
7582 }
7583 else
7584 if (shid == SVGA_ID_INVALID)
7585 {
7586 /* Unselect shader. */
7587 rc = ShaderSetPixelShader(pContext->pShaderContext, NULL);
7588 AssertRCReturn(rc, rc);
7589 }
7590 else
7591 AssertFailedReturn(VERR_INVALID_PARAMETER);
7592 }
7593
7594 return VINF_SUCCESS;
7595}
7596
7597static DECLCALLBACK(int) vmsvga3dBackShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues)
7598{
7599 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7600 AssertReturn(pState, VERR_NO_MEMORY);
7601
7602 Log(("vmsvga3dShaderSetConst cid=%u reg=%x type=%s cregs=%d ctype=%x\n", cid, reg, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cRegisters, ctype));
7603
7604 PVMSVGA3DCONTEXT pContext;
7605 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
7606 AssertRCReturn(rc, rc);
7607
7608 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7609
7610 for (uint32_t i = 0; i < cRegisters; i++)
7611 {
7612#ifdef LOG_ENABLED
7613 switch (ctype)
7614 {
7615 case SVGA3D_CONST_TYPE_FLOAT:
7616 {
7617 float *pValuesF = (float *)pValues;
7618 Log(("ConstantF %d: value=" FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "\n",
7619 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])));
7620 break;
7621 }
7622
7623 case SVGA3D_CONST_TYPE_INT:
7624 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]));
7625 break;
7626
7627 case SVGA3D_CONST_TYPE_BOOL:
7628 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]));
7629 break;
7630
7631 default:
7632 AssertFailedReturn(VERR_INVALID_PARAMETER);
7633 }
7634#endif
7635 vmsvga3dSaveShaderConst(pContext, reg + i, type, ctype, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]);
7636 }
7637
7638 switch (type)
7639 {
7640 case SVGA3D_SHADERTYPE_VS:
7641 switch (ctype)
7642 {
7643 case SVGA3D_CONST_TYPE_FLOAT:
7644 rc = ShaderSetVertexShaderConstantF(pContext->pShaderContext, reg, (const float *)pValues, cRegisters);
7645 break;
7646
7647 case SVGA3D_CONST_TYPE_INT:
7648 rc = ShaderSetVertexShaderConstantI(pContext->pShaderContext, reg, (const int32_t *)pValues, cRegisters);
7649 break;
7650
7651 case SVGA3D_CONST_TYPE_BOOL:
7652 rc = ShaderSetVertexShaderConstantB(pContext->pShaderContext, reg, (const uint8_t *)pValues, cRegisters);
7653 break;
7654
7655 default:
7656 AssertFailedReturn(VERR_INVALID_PARAMETER);
7657 }
7658 AssertRCReturn(rc, rc);
7659 break;
7660
7661 case SVGA3D_SHADERTYPE_PS:
7662 switch (ctype)
7663 {
7664 case SVGA3D_CONST_TYPE_FLOAT:
7665 rc = ShaderSetPixelShaderConstantF(pContext->pShaderContext, reg, (const float *)pValues, cRegisters);
7666 break;
7667
7668 case SVGA3D_CONST_TYPE_INT:
7669 rc = ShaderSetPixelShaderConstantI(pContext->pShaderContext, reg, (const int32_t *)pValues, cRegisters);
7670 break;
7671
7672 case SVGA3D_CONST_TYPE_BOOL:
7673 rc = ShaderSetPixelShaderConstantB(pContext->pShaderContext, reg, (const uint8_t *)pValues, cRegisters);
7674 break;
7675
7676 default:
7677 AssertFailedReturn(VERR_INVALID_PARAMETER);
7678 }
7679 AssertRCReturn(rc, rc);
7680 break;
7681
7682 default:
7683 AssertFailedReturn(VERR_INVALID_PARAMETER);
7684 }
7685
7686 return VINF_SUCCESS;
7687}
7688
7689static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryCreate(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7690{
7691 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7692 AssertReturn(pState->ext.glGenQueries, VERR_NOT_SUPPORTED);
7693 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7694
7695 GLuint idQuery = 0;
7696 pState->ext.glGenQueries(1, &idQuery);
7697 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7698 AssertReturn(idQuery, VERR_INTERNAL_ERROR);
7699 pContext->occlusion.idQuery = idQuery;
7700 return VINF_SUCCESS;
7701}
7702
7703static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryDelete(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7704{
7705 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7706 AssertReturn(pState->ext.glDeleteQueries, VERR_NOT_SUPPORTED);
7707 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7708
7709 if (pContext->occlusion.idQuery)
7710 {
7711 pState->ext.glDeleteQueries(1, &pContext->occlusion.idQuery);
7712 }
7713 return VINF_SUCCESS;
7714}
7715
7716static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryBegin(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7717{
7718 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7719 AssertReturn(pState->ext.glBeginQuery, VERR_NOT_SUPPORTED);
7720 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7721
7722 pState->ext.glBeginQuery(GL_ANY_SAMPLES_PASSED, pContext->occlusion.idQuery);
7723 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7724 return VINF_SUCCESS;
7725}
7726
7727static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryEnd(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
7728{
7729 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7730 AssertReturn(pState->ext.glEndQuery, VERR_NOT_SUPPORTED);
7731 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7732
7733 pState->ext.glEndQuery(GL_ANY_SAMPLES_PASSED);
7734 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7735 return VINF_SUCCESS;
7736}
7737
7738static DECLCALLBACK(int) vmsvga3dBackOcclusionQueryGetData(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext, uint32_t *pu32Pixels)
7739{
7740 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7741 AssertReturn(pState->ext.glGetQueryObjectuiv, VERR_NOT_SUPPORTED);
7742 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7743
7744 GLuint pixels = 0;
7745 pState->ext.glGetQueryObjectuiv(pContext->occlusion.idQuery, GL_QUERY_RESULT, &pixels);
7746 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7747
7748 *pu32Pixels = (uint32_t)pixels;
7749 return VINF_SUCCESS;
7750}
7751
7752/**
7753 * Worker for vmsvga3dUpdateHeapBuffersForSurfaces.
7754 *
7755 * This will allocate heap buffers if necessary, thus increasing the memory
7756 * usage of the process.
7757 *
7758 * @todo Would be interesting to share this code with the saved state code.
7759 *
7760 * @returns VBox status code.
7761 * @param pThisCC The VGA/VMSVGA context.
7762 * @param pSurface The surface to refresh the heap buffers for.
7763 */
7764static DECLCALLBACK(int) vmsvga3dBackSurfaceUpdateHeapBuffers(PVGASTATECC pThisCC, PVMSVGA3DSURFACE pSurface)
7765{
7766 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
7767 AssertReturn(pState, VERR_INVALID_STATE);
7768
7769 /*
7770 * Currently we've got trouble retreving bit for DEPTHSTENCIL
7771 * surfaces both for OpenGL and D3D, so skip these here (don't
7772 * wast memory on them).
7773 */
7774 uint32_t const fSwitchFlags = pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK;
7775 if ( fSwitchFlags != SVGA3D_SURFACE_HINT_DEPTHSTENCIL
7776 && fSwitchFlags != (SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE))
7777 {
7778 /*
7779 * Change OpenGL context to the one the surface is associated with.
7780 */
7781 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
7782 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
7783
7784 /*
7785 * Work thru each mipmap level for each face.
7786 */
7787 for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++)
7788 {
7789 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[iFace * pSurface->cLevels];
7790 for (uint32_t i = 0; i < pSurface->cLevels; i++, pMipmapLevel++)
7791 {
7792 if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
7793 {
7794 Assert(pMipmapLevel->cbSurface);
7795 Assert(pMipmapLevel->cbSurface == pMipmapLevel->cbSurfacePlane * pMipmapLevel->mipmapSize.depth);
7796
7797 /*
7798 * Make sure we've got surface memory buffer.
7799 */
7800 uint8_t *pbDst = (uint8_t *)pMipmapLevel->pSurfaceData;
7801 if (!pbDst)
7802 {
7803 pMipmapLevel->pSurfaceData = pbDst = (uint8_t *)RTMemAllocZ(pMipmapLevel->cbSurface);
7804 AssertReturn(pbDst, VERR_NO_MEMORY);
7805 }
7806
7807 /*
7808 * OpenGL specifics.
7809 */
7810 switch (pSurface->enmOGLResType)
7811 {
7812 case VMSVGA3D_OGLRESTYPE_TEXTURE:
7813 {
7814 GLint activeTexture;
7815 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
7816 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7817
7818 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
7819 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7820
7821 /* Set row length and alignment of the output data. */
7822 VMSVGAPACKPARAMS SavedParams;
7823 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
7824
7825 glGetTexImage(GL_TEXTURE_2D,
7826 i,
7827 pSurface->formatGL,
7828 pSurface->typeGL,
7829 pbDst);
7830 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7831
7832 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
7833
7834 /* Restore the old active texture. */
7835 glBindTexture(GL_TEXTURE_2D, activeTexture);
7836 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
7837 break;
7838 }
7839
7840 case VMSVGA3D_OGLRESTYPE_BUFFER:
7841 {
7842 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
7843 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7844
7845 void *pvSrc = pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
7846 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7847 if (RT_VALID_PTR(pvSrc))
7848 memcpy(pbDst, pvSrc, pMipmapLevel->cbSurface);
7849 else
7850 AssertPtr(pvSrc);
7851
7852 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
7853 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7854
7855 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
7856 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
7857 break;
7858 }
7859
7860 default:
7861 AssertMsgFailed(("%#x\n", fSwitchFlags));
7862 }
7863 }
7864 /* else: There is no data in hardware yet, so whatever we got is already current. */
7865 }
7866 }
7867 }
7868
7869 return VINF_SUCCESS;
7870}
7871
7872static DECLCALLBACK(int) vmsvga3dBackQueryInterface(PVGASTATECC pThisCC, char const *pszInterfaceName, void *pvInterfaceFuncs, size_t cbInterfaceFuncs)
7873{
7874 RT_NOREF(pThisCC);
7875
7876 int rc = VINF_SUCCESS;
7877 if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_3D) == 0)
7878 {
7879 if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCS3D))
7880 {
7881 if (pvInterfaceFuncs)
7882 {
7883 VMSVGA3DBACKENDFUNCS3D *p = (VMSVGA3DBACKENDFUNCS3D *)pvInterfaceFuncs;
7884 p->pfnInit = vmsvga3dBackInit;
7885 p->pfnPowerOn = vmsvga3dBackPowerOn;
7886 p->pfnTerminate = vmsvga3dBackTerminate;
7887 p->pfnReset = vmsvga3dBackReset;
7888 p->pfnQueryCaps = vmsvga3dBackQueryCaps;
7889 p->pfnChangeMode = vmsvga3dBackChangeMode;
7890 p->pfnCreateTexture = vmsvga3dBackCreateTexture;
7891 p->pfnSurfaceDestroy = vmsvga3dBackSurfaceDestroy;
7892 p->pfnSurfaceCopy = vmsvga3dBackSurfaceCopy;
7893 p->pfnSurfaceDMACopyBox = vmsvga3dBackSurfaceDMACopyBox;
7894 p->pfnSurfaceStretchBlt = vmsvga3dBackSurfaceStretchBlt;
7895 p->pfnUpdateHostScreenViewport = vmsvga3dBackUpdateHostScreenViewport;
7896 p->pfnDefineScreen = vmsvga3dBackDefineScreen;
7897 p->pfnDestroyScreen = vmsvga3dBackDestroyScreen;
7898 p->pfnSurfaceBlitToScreen = vmsvga3dBackSurfaceBlitToScreen;
7899 p->pfnSurfaceUpdateHeapBuffers = vmsvga3dBackSurfaceUpdateHeapBuffers;
7900 }
7901 }
7902 else
7903 {
7904 AssertFailed();
7905 rc = VERR_INVALID_PARAMETER;
7906 }
7907 }
7908 else if (RTStrCmp(pszInterfaceName, VMSVGA3D_BACKEND_INTERFACE_NAME_VGPU9) == 0)
7909 {
7910 if (cbInterfaceFuncs == sizeof(VMSVGA3DBACKENDFUNCSVGPU9))
7911 {
7912 if (pvInterfaceFuncs)
7913 {
7914 VMSVGA3DBACKENDFUNCSVGPU9 *p = (VMSVGA3DBACKENDFUNCSVGPU9 *)pvInterfaceFuncs;
7915 p->pfnContextDefine = vmsvga3dBackContextDefine;
7916 p->pfnContextDestroy = vmsvga3dBackContextDestroy;
7917 p->pfnSetTransform = vmsvga3dBackSetTransform;
7918 p->pfnSetZRange = vmsvga3dBackSetZRange;
7919 p->pfnSetRenderState = vmsvga3dBackSetRenderState;
7920 p->pfnSetRenderTarget = vmsvga3dBackSetRenderTarget;
7921 p->pfnSetTextureState = vmsvga3dBackSetTextureState;
7922 p->pfnSetMaterial = vmsvga3dBackSetMaterial;
7923 p->pfnSetLightData = vmsvga3dBackSetLightData;
7924 p->pfnSetLightEnabled = vmsvga3dBackSetLightEnabled;
7925 p->pfnSetViewPort = vmsvga3dBackSetViewPort;
7926 p->pfnSetClipPlane = vmsvga3dBackSetClipPlane;
7927 p->pfnCommandClear = vmsvga3dBackCommandClear;
7928 p->pfnDrawPrimitives = vmsvga3dBackDrawPrimitives;
7929 p->pfnSetScissorRect = vmsvga3dBackSetScissorRect;
7930 p->pfnGenerateMipmaps = vmsvga3dBackGenerateMipmaps;
7931 p->pfnShaderDefine = vmsvga3dBackShaderDefine;
7932 p->pfnShaderDestroy = vmsvga3dBackShaderDestroy;
7933 p->pfnShaderSet = vmsvga3dBackShaderSet;
7934 p->pfnShaderSetConst = vmsvga3dBackShaderSetConst;
7935 p->pfnOcclusionQueryCreate = vmsvga3dBackOcclusionQueryCreate;
7936 p->pfnOcclusionQueryDelete = vmsvga3dBackOcclusionQueryDelete;
7937 p->pfnOcclusionQueryBegin = vmsvga3dBackOcclusionQueryBegin;
7938 p->pfnOcclusionQueryEnd = vmsvga3dBackOcclusionQueryEnd;
7939 p->pfnOcclusionQueryGetData = vmsvga3dBackOcclusionQueryGetData;
7940 }
7941 }
7942 else
7943 {
7944 AssertFailed();
7945 rc = VERR_INVALID_PARAMETER;
7946 }
7947 }
7948 else
7949 rc = VERR_NOT_IMPLEMENTED;
7950 return rc;
7951}
7952
7953
7954extern VMSVGA3DBACKENDDESC const g_BackendLegacy =
7955{
7956 "LEGACY",
7957 vmsvga3dBackQueryInterface
7958};
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use