| 
									
										
										
										
											2008-09-07 10:29:46 +00:00
										 |  |  | // Copyright (C) 2003-2008 Dolphin Project.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 20:54:40 +00:00
										 |  |  | #include "Common.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | #include "D3DBase.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 20:54:40 +00:00
										 |  |  | #include "Statistics.h"
 | 
					
						
							| 
									
										
										
										
											2008-10-17 11:30:14 +00:00
										 |  |  | #include "Profiler.h"
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | #include "VertexManager.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | #include "OpcodeDecoding.h"
 | 
					
						
							|  |  |  | #include "TransformEngine.h"
 | 
					
						
							|  |  |  | #include "IndexGenerator.h"
 | 
					
						
							|  |  |  | #include "BPStructs.h"
 | 
					
						
							|  |  |  | #include "XFStructs.h"
 | 
					
						
							|  |  |  | #include "ShaderManager.h"
 | 
					
						
							|  |  |  | #include "Utils.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace D3D; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | namespace VertexManager | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static IndexGenerator indexGen; | 
					
						
							|  |  |  | static Collection collection; | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | static LPDIRECT3DVERTEXDECLARATION9 vDecl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static D3DVertex *fakeVBuffer; | 
					
						
							|  |  |  | static u16 *fakeIBuffer; | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MAXVBUFFERSIZE 65536*3
 | 
					
						
							|  |  |  | #define MAXIBUFFERSIZE 65536*3
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const D3DVERTEXELEMENT9 decl[] = | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     { 0,  0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, | 
					
						
							|  |  |  |     { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, | 
					
						
							|  |  |  |     { 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, | 
					
						
							|  |  |  |     { 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 }, | 
					
						
							|  |  |  | 	{ 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 }, | 
					
						
							|  |  |  |     D3DDECL_END() | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool Init() | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	collection = C_NOTHING; | 
					
						
							|  |  |  | 	fakeVBuffer = new D3DVertex[65536]; | 
					
						
							|  |  |  | 	fakeIBuffer = new u16[65536]; | 
					
						
							|  |  |  | 	CreateDeviceObjects(); | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | void Shutdown() | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	DestroyDeviceObjects(); | 
					
						
							|  |  |  | 	delete [] fakeVBuffer; | 
					
						
							|  |  |  | 	delete [] fakeIBuffer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | void CreateDeviceObjects() | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	HRESULT hr; | 
					
						
							| 
									
										
										
										
											2008-10-25 13:27:28 +00:00
										 |  |  | 	if (FAILED(hr = D3D::dev->CreateVertexDeclaration(decl, &vDecl))) | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  |     { | 
					
						
							|  |  |  | 		MessageBox(0,"Failed to create vertex declaration","sdfsd",0); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | void BeginFrame() | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	D3D::dev->SetVertexDeclaration(vDecl); | 
					
						
							|  |  |  | 	//D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex));
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | void DestroyDeviceObjects() | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (vDecl) | 
					
						
							|  |  |  | 		vDecl->Release(); | 
					
						
							| 
									
										
										
										
											2008-10-25 13:27:28 +00:00
										 |  |  | 	vDecl = 0; | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | void AddIndices(int _primitive, int _numVertices) | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	switch(_primitive) { | 
					
						
							|  |  |  | 	case GX_DRAW_QUADS:          indexGen.AddQuads(_numVertices); return;     | 
					
						
							|  |  |  | 	case GX_DRAW_TRIANGLES:      indexGen.AddList(_numVertices);  return;     | 
					
						
							|  |  |  | 	case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices);     return; | 
					
						
							|  |  |  | 	case GX_DRAW_TRIANGLE_FAN:   indexGen.AddFan(_numVertices);       return; | 
					
						
							|  |  |  | 	case GX_DRAW_LINE_STRIP:     indexGen.AddLineStrip(_numVertices); return; | 
					
						
							|  |  |  | 	case GX_DRAW_LINES:		     indexGen.AddLineList(_numVertices);  return; | 
					
						
							|  |  |  | 	case GX_DRAW_POINTS:         indexGen.AddPointList(_numVertices); return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Collection collectionTypeLUT[8] = | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	C_TRIANGLES,//quads
 | 
					
						
							|  |  |  | 	C_NOTHING,  //nothing
 | 
					
						
							|  |  |  | 	C_TRIANGLES,//triangles
 | 
					
						
							|  |  |  | 	C_TRIANGLES,//strip
 | 
					
						
							|  |  |  | 	C_TRIANGLES,//fan
 | 
					
						
							|  |  |  | 	C_LINES,    //lines
 | 
					
						
							|  |  |  | 	C_LINES,    //linestrip
 | 
					
						
							|  |  |  | 	C_POINTS    //guess :P
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | D3DVertex *vbufferwrite; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | void AddVertices(int _primitive, int _numVertices, const DecodedVArray *varray) | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (_numVertices <= 0) //This check is pretty stupid... 
 | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	Collection type = collectionTypeLUT[_primitive]; | 
					
						
							|  |  |  | 	if (type == C_NOTHING) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DVSTARTPROFILE(); | 
					
						
							|  |  |  | 	_assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF"); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise?
 | 
					
						
							|  |  |  | 		Flush(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADDSTAT(stats.thisFrame.numPrims, _numVertices); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (collection != type) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		//We are NOT collecting the right type.
 | 
					
						
							|  |  |  | 		Flush(); | 
					
						
							|  |  |  | 		collection = type; | 
					
						
							|  |  |  | 		u16 *ptr = 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		if (type != C_POINTS) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ptr = fakeIBuffer; | 
					
						
							|  |  |  | 			indexGen.Start((unsigned short*)ptr); | 
					
						
							|  |  |  | 			AddIndices(_primitive,_numVertices); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		vbufferwrite = fakeVBuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (_numVertices >= MAXVBUFFERSIZE) | 
					
						
							|  |  |  | 			MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | 		CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite); | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else //We are collecting the right type, keep going
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		_assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF"); | 
					
						
							|  |  |  | 		INCSTAT(stats.numJoins); | 
					
						
							|  |  |  | 		//Success, keep adding to unlocked buffer
 | 
					
						
							|  |  |  | 		int last=indexGen.GetNumVerts(); | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | 		AddIndices(_primitive, _numVertices); | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (_numVertices >= MAXVBUFFERSIZE) | 
					
						
							|  |  |  | 			MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK); | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | 		CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite + last); | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const D3DPRIMITIVETYPE pts[3] =  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	D3DPT_POINTLIST, //DUMMY
 | 
					
						
							|  |  |  | 	D3DPT_TRIANGLELIST,  | 
					
						
							|  |  |  | 	D3DPT_LINELIST, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | void Flush() | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     DVSTARTPROFILE(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (collection != C_NOTHING) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ActivateTextures(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int numVertices = indexGen.GetNumVerts(); | 
					
						
							|  |  |  | 		if (numVertices != 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
 | 
					
						
							|  |  |  | 			VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
 | 
					
						
							|  |  |  | 			if (collection != C_POINTS) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int numPrimitives = indexGen.GetNumPrims(); | 
					
						
							|  |  |  | 				D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection],  | 
					
						
							|  |  |  | 					                             0,  | 
					
						
							|  |  |  | 												 numVertices,  | 
					
						
							|  |  |  | 												 numPrimitives, | 
					
						
							|  |  |  | 												 fakeIBuffer, | 
					
						
							|  |  |  | 												 D3DFMT_INDEX16, | 
					
						
							|  |  |  | 												 fakeVBuffer, | 
					
						
							|  |  |  | 												 sizeof(D3DVertex)); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				D3D::dev->SetIndices(0); | 
					
						
							| 
									
										
										
										
											2008-08-17 19:28:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST,
 | 
					
						
							|  |  |  | 				//	                      numVertices,
 | 
					
						
							|  |  |  | 				//						  fakeVBuffer,
 | 
					
						
							|  |  |  | 				//						  sizeof(D3DVertex));
 | 
					
						
							|  |  |  | 				Renderer::DrawPrimitiveUP( D3DPT_POINTLIST, numVertices, fakeVBuffer, sizeof(D3DVertex) ); | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		collection = C_NOTHING; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-27 21:38:30 +00:00
										 |  |  | }  // namespace
 |