VirtualBox

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

Last change on this file since 82109 was 82109, checked in by vboxsync, 5 years ago

DevVGA: Splitting up the VGASTATE structure. bugref:9218

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