VirtualBox

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

Last change on this file since 53752 was 53750, checked in by vboxsync, 10 years ago

build fix

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