VirtualBox

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

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

VMSVGA3d/darwin: Using the use OpenGL 3.2 Core profile works better, but there are some snags like glGetString(GT_EXTENSIONS). Addressed a bunch of warnings.

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

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