VirtualBox

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

Last change on this file since 57801 was 57790, checked in by vboxsync, 9 years ago

VMSVGA3d: Turns out I'm blitting to the wrong end (Y direction) of the nsview framebuffer. Missed some [NSOpenGLContext update] calls when the parent view got resized, so it sometimes worked, but not all the time. After calling update, the visible part of the framebuffer is the bottom half, not the top half as I though and as seems to be the case on the other plaforms.

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