VirtualBox

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

Last change on this file since 94377 was 94063, checked in by vboxsync, 3 years ago

Devices/Graphics: shader resource and render target views should be set before a Draw call; resource view cleanup: bugref:9830

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

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