/* * SVGA3D example: Present Reaback example. This example tests the 3d * and 2d syncronization presentReadback command. This example draws * a spinning cube using 3d. After every frame parts of the 2d * framebuffer are updated with present readback with a 2d update * following. Parts of the 3d region are cleared before the present * readback command testing that the last presented 3d data is what is * copied to the 2d framebuffer. This cube should spin with no * flicker. * * Copyright (C) 2008-2009 VMware, Inc. Licensed under the MIT * License, please see the README.txt. All rights reserved. */ #include "svga3dutil.h" #include "svga3dtext.h" #include "matrix.h" #include "math.h" typedef struct { float position[3]; uint32 color; } MyVertex; static const MyVertex vertexData[] = { { {-1, -1, -1}, 0xFFFFFF }, { {-1, -1, 1}, 0xFFFF00 }, { {-1, 1, -1}, 0xFF00FF }, { {-1, 1, 1}, 0xFF0000 }, { { 1, -1, -1}, 0x00FFFF }, { { 1, -1, 1}, 0x00FF00 }, { { 1, 1, -1}, 0x0000FF }, { { 1, 1, 1}, 0x000000 }, }; #define QUAD(a,b,c,d) a, b, d, d, c, a static const uint16 indexData[] = { QUAD(0,1,2,3), // -X QUAD(4,5,6,7), // +X QUAD(0,1,4,5), // -Y QUAD(2,3,6,7), // +Y QUAD(0,2,4,6), // -Z QUAD(1,3,5,7), // +Z }; #undef QUAD const uint32 numTriangles = sizeof indexData / sizeof indexData[0] / 3; uint32 vertexSid, indexSid; Matrix perspectiveMat; FPSCounterState gFPS; VMMousePacket lastMouseState; /* * render -- * * Set up render state, and draw our cube scene from static index * and vertex buffers. * * This render state only needs to be set each frame because * SVGA3DText_Draw() changes it. */ void render(void) { SVGA3dTextureState *ts; SVGA3dRenderState *rs; SVGA3dVertexDecl *decls; SVGA3dPrimitiveRange *ranges; static Matrix view; Matrix_Copy(view, gIdentityMatrix); Matrix_Scale(view, 0.5, 0.5, 0.5, 1.0); if (lastMouseState.buttons & VMMOUSE_LEFT_BUTTON) { Matrix_RotateX(view, lastMouseState.y * 0.0001); Matrix_RotateY(view, lastMouseState.x * -0.0001); } else { Matrix_RotateX(view, 30.0 * M_PI / 180.0); Matrix_RotateY(view, gFPS.frame * 0.01f); } Matrix_Translate(view, 0, 0, 3); SVGA3D_SetTransform(CID, SVGA3D_TRANSFORM_VIEW, view); SVGA3D_SetTransform(CID, SVGA3D_TRANSFORM_WORLD, gIdentityMatrix); SVGA3D_SetTransform(CID, SVGA3D_TRANSFORM_PROJECTION, perspectiveMat); SVGA3D_BeginSetRenderState(CID, &rs, 4); { rs[0].state = SVGA3D_RS_BLENDENABLE; rs[0].uintValue = FALSE; rs[1].state = SVGA3D_RS_ZENABLE; rs[1].uintValue = TRUE; rs[2].state = SVGA3D_RS_ZWRITEENABLE; rs[2].uintValue = TRUE; rs[3].state = SVGA3D_RS_ZFUNC; rs[3].uintValue = SVGA3D_CMP_LESS; } SVGA_FIFOCommitAll(); SVGA3D_BeginSetTextureState(CID, &ts, 4); { ts[0].stage = 0; ts[0].name = SVGA3D_TS_BIND_TEXTURE; ts[0].value = SVGA3D_INVALID_ID; ts[1].stage = 0; ts[1].name = SVGA3D_TS_COLOROP; ts[1].value = SVGA3D_TC_SELECTARG1; ts[2].stage = 0; ts[2].name = SVGA3D_TS_COLORARG1; ts[2].value = SVGA3D_TA_DIFFUSE; ts[3].stage = 0; ts[3].name = SVGA3D_TS_ALPHAARG1; ts[3].value = SVGA3D_TA_DIFFUSE; } SVGA_FIFOCommitAll(); SVGA3D_BeginDrawPrimitives(CID, &decls, 2, &ranges, 1); { decls[0].identity.type = SVGA3D_DECLTYPE_FLOAT3; decls[0].identity.usage = SVGA3D_DECLUSAGE_POSITION; decls[0].array.surfaceId = vertexSid; decls[0].array.stride = sizeof(MyVertex); decls[0].array.offset = offsetof(MyVertex, position); decls[1].identity.type = SVGA3D_DECLTYPE_D3DCOLOR; decls[1].identity.usage = SVGA3D_DECLUSAGE_COLOR; decls[1].array.surfaceId = vertexSid; decls[1].array.stride = sizeof(MyVertex); decls[1].array.offset = offsetof(MyVertex, color); ranges[0].primType = SVGA3D_PRIMITIVE_TRIANGLELIST; ranges[0].primitiveCount = numTriangles; ranges[0].indexArray.surfaceId = indexSid; ranges[0].indexArray.stride = sizeof(uint16); ranges[0].indexWidth = sizeof(uint16); } SVGA_FIFOCommitAll(); } /* * main -- * * Our example's entry point, invoked directly by the bootloader. */ int main(void) { SVGAGuestPtr ptr; SVGA3DUtil_InitFullscreen(CID, 800, 600); SVGA3DUtil_AllocDMABuffer(gSVGA.width * gSVGA.height * 4, &ptr); SVGA3DText_Init(); vertexSid = SVGA3DUtil_DefineStaticBuffer(vertexData, sizeof vertexData); indexSid = SVGA3DUtil_DefineStaticBuffer(indexData, sizeof indexData); Matrix_Perspective(perspectiveMat, 45.0f, gSVGA.width / (float)gSVGA.height, 0.1f, 100.0f); while (1) { SVGA3dRect *rects; int halfWidth = gSVGA.width / 2; int halfHeight = gSVGA.height / 2; if (SVGA3DUtil_UpdateFPSCounter(&gFPS)) { Console_Clear(); Console_Format("VMware SVGA3D Example:\n" "Present Readback:\n" " - upper left quadrant:\n" " present\n" " - lower right quadrant:\n" " present -> presentReadback -> update\n" " - upper right and lower left quadrants:\n" " present -> clear -> presentReadback -> update\n" "\n" "The cube should appear to be smothly spinning \n" "with all quadrants of the screen in sync.\n\n%s", gFPS.text); SVGA3DText_Update(); VMBackdoor_VGAScreenshot(); } while (VMBackdoor_MouseGetPacket(&lastMouseState)); SVGA3DUtil_ClearFullscreen(CID, SVGA3D_CLEAR_COLOR | SVGA3D_CLEAR_DEPTH, 0x113366, 1.0f, 0); render(); SVGA3DText_Draw(); SVGA3DUtil_PresentFullscreen(); SVGA3D_BeginPresentReadback(&rects, 1); rects[0].x = halfWidth; rects[0].y = halfHeight; rects[0].w = halfWidth; rects[0].h = halfHeight; SVGA_FIFOCommitAll(); SVGA_SyncToFence(SVGA_InsertFence()); SVGA_Update(halfWidth,halfHeight,halfWidth,halfHeight); SVGA3DUtil_ClearFullscreen(CID, SVGA3D_CLEAR_COLOR | SVGA3D_CLEAR_DEPTH, 0xff00ff, 1.0f, 0); SVGA3D_BeginPresentReadback(&rects, 2); rects[0].x = halfWidth; rects[0].y = 0; rects[0].w = halfWidth; rects[0].h = halfHeight; rects[1].x = 0; rects[1].y = halfHeight; rects[1].w = halfWidth; rects[1].h = halfHeight; SVGA_FIFOCommitAll(); SVGA_SyncToFence(SVGA_InsertFence()); SVGA_Update(halfWidth, 0, halfWidth, halfHeight); SVGA_Update(0, halfHeight, halfWidth, halfHeight); } return 0; }